I get the exception:
Warning: StandardWrapperValve[org.netbeans.rest.application.config.ApplicationConfig]: Servlet.service() for servlet org.netbeans.rest.application.config.ApplicationConfig threw exception
javax.ejb.AccessLocalException: Client not authorized for this invocation
This is perfectly normal, as it is not authorized for this methodcall.
Onfortunately, as this EJB is a REST Service as well, it throws a "500 - Bad Request" http status. Instead I would like to have a "401 - Unauthorized".
Should I not use EJB Security or should I catch this AccessLocalException in the ApplicationConfig or should I use Jersey to implement REST Security?
Roles are defined in the web.xml and annotations are put upon the EJB Bean.
You can define an ExceptionMapper, that maps a General Exception onto a HTTP Response.
import javax.ejb.EJBAccessException;
import javax.ws.rs.core.Response;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
#Provider
public class EJBAccessExceptionMapper implements
ExceptionMapper<EJBAccessException>
{
#Override
public Response toResponse(EJBAccessException exception)
{
return Response.status(Response.Status.UNAUTHORIZED).build();
}
}
Related
How to implement multipart/form-data request (file upload) handler with JAX-RS without vendor specific libraries? So far I haven't found other way than to inject the HttpServletRequest and use the Servlet API to access the form data.
Yet HttpServletRequest#getParts() returns an empty list even the request is well formed (confirmed with Wireshark). I read I have to enable multipart configuration for the Jersey Servlet in the web.xml. However, I'm using #ApplicationPath annotation to automatically configure JAX-RS. So what is the correct way to handle multipart requests?
This code may inspire you
1) JAXRS App setup
import javax.ws.rs.ApplicationPath;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.media.multipart.MultiPartFeature;
#ApplicationPath("demo")
public class ApplicationConfig extends ResourceConfig {
public ApplicationConfig() {
packages("com.mycompany.demo").register(MultiPartFeature.class); // <= here!
}
}
2) JAXRS service
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadImage(
#FormDataParam("file") InputStream data,
#FormDataParam("file") FormDataContentDisposition fileInfo) {
...
}
I am building REST API with Spring Boot and I use Spring Security. I started here but found some other tutorials and blog posts with this issue and managed to get it work after implementing custom stuff. This and this SO posts answer some of my questions, but I have one more:
Is there any extension that implements some of the things like REST AuthenticationEntryPoint that returns 401 instead of redirect, or JWT generating and verifying or I should just implement same things for every REST service?
Thank you for your answers.
I also use Springboot but for the security I rely on Apache Shiro project which fundamentally, depending how you store the users accounts (mines are in a MongoDb instance),
takes care of the login - currentUser.login(token);
If fails throws an exception so you can handle the response
If succeed inject the authentication cookie in the response
For any other request, decode the cookie and inject the user with the proper authorizations
In few words Shiro does not redirect the HTTPRequest because it just care for the security leaving further decision, redirect in your case, to your controller logic.
You can add it to your project with a simple Maven dependence.
#brownies.....
try this one....
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
#Component
public class RESTAuthenticationEntryPoint implements AuthenticationEntryPoint {
#Override
public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}
#Autowired
private RESTAuthenticationEntryPoint restAuthenticationEntryPoint;
#Override
protected void configure(final HttpSecurity http) throws Exception {
http.cors().and().exceptionHandling().authenticationEntryPoint(restAuthenticationEntryPoint).and().authorizeRequests()......
add above RESTAuthenticationEntryPoint and config in your security configuration class then it will return 401 if auth fails.
I'm learning REST web service. I need some clarification on handling custom exception in Jersey. By using WebApplicationException and ExceptionMapper you can throw custom Exception. My question is in which scenario we have go for WebApplicationException and ExceptionMapper. What are the differences between them?
I've gone through with some tutorial, I found that ExceptionMapper is like Generic.
#Provider
class MyWrapper implements ExceptionMapper<MyPojoClass>
{
}
One more difference is that,
Because of #Provider Jersey will catch this exception only by default, if any other exception occurs also.
Is there any other differences?
MyExceptionMapper.java
package com.katte.galaxe.exception;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.ExceptionMapper;
import javax.ws.rs.ext.Provider;
public class MyExceptionMapper implements ExceptionMapper<MyCustomException>
{
#Override
public Response toResponse(MyCustomException errMsg) {
ErrorMessage msg = new ErrorMessage(errMsg.getMessage(),1100);
return Response.status(Status.NOT_FOUND)
.type(MediaType.APPLICATION_XML)
.entity(msg)
.build();
}
}
MyWebApplicationException.java
package com.katte.galaxe.exception;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
public class MyWebApplicationException extends WebApplicationException{
private static final long serialVersionUID = -5788907118191114665L;
public MyWebApplicationException(ErrorMessage msg) {
super(Response.status(Status.NOT_FOUND)
.entity(msg)
.type(MediaType.APPLICATION_XML)
.build());
}
}
WebApplicationException and ExceptionMapper are not meant to be compared as they serve different purpose. Instead they are meant to be used together for a better response strategy.
Imagine a case wherein an exception is encountered while serving a request. Let's say you encountered a SQLException while accessing a database. In this case one can make use of ExceptionMapper to map SQLException with an appropriate 5xx response instead of propagating the original exception to the end user.
WebApplicationException
Runtime exception for applications.
This exception may be thrown by a resource method, provider or StreamingOutput implementation if a specific HTTP error response needs to be produced. Only effective if thrown prior to the response being committed.
ExceptionMapper
Contract for a provider that maps Java exceptions to Response.
I'm trying to test a resource with Resteasy using an embedded Netty instance as described in the Resteasy Docs.
Injecting path parameters and query parameters works like a charm but then I tried to test a resource that injects HttpServletRequest and HttpServletResponse from the context like this:
#GET
#Path("/")
public void example(#Context HttpServletResponse response,
#Context HttpServletRequest request) { ... }
Resteasy cannot find HttpServletRequestin the context and throws the following exception:
5105 [r #1] DEB o.j.resteasy.core.SynchronousDispatcher - PathInfo: /auth
5201 [r #1] ERR c.s.f.v.s.r.e.ApplicationExceptionMapper - Unhandled application exception: Unable to find contextual data of type: javax.servlet.http.HttpServletRequest
org.jboss.resteasy.spi.LoggableFailure: Unable to find contextual data of type: javax.servlet.http.HttpServletRequest
I tried putting mock versions of request and response in the context as suggested in RESTEasy Mock vs. Exception Mapper vs. Context but it does not work either as the contextual data is a ThreadLocal and Netty spawns a new thread for each request.
Any ideas on how to solve this?
What worked in my case was injecting a org.jboss.seam.mock.HttpServletRequest, since I am using seam in my application. You should try some mock framework like spring.test or mockito.
Here is how my code looks like:
import org.jboss.resteasy.core.Dispatcher;
import org.jboss.resteasy.mock.MockDispatcherFactory;
import org.jboss.resteasy.mock.MockHttpRequest;
import org.jboss.resteasy.mock.MockHttpResponse;
import org.jboss.resteasy.plugins.server.resourcefactory.POJOResourceFactory;
import org.jboss.resteasy.spi.ResteasyProviderFactory;
import org.jboss.seam.mock.MockHttpServletRequest;
import org.jboss.seam.mock.DBUnitSeamTest;
public class Test extends DBUnitSeamTest{
#Test
public void test() throws Exception {
Dispatcher dispatcher = MockDispatcherFactory.createDispatcher();
POJOResourceFactory noDefaults = new POJOResourceFactory(ClasstoBeTested.class); dispatcher.getRegistry().addResourceFactory(noDefaults);
MockHttpRequest request = MockHttpRequest.get("/serviceToBeTested/1961");
MockHttpResponse response = new MockHttpResponse();
HttpServletRequest servletRequest = new MockHttpServletRequest(getSession());
ResteasyProviderFactory.getContextDataMap().put(HttpServletRequest.class, servletRequest);
dispatcher.invoke(request, response);
Assert.assertEquals(HttpServletResponse.SC_OK, response.getStatus());
Assert.assertTrue(response.getContentAsString().contains("1961"));
}
}
I just got hit by this again on another project and decided to investigate once more.
The issue is that in a mock request with Netty, there is no HttpServletRequest available. If you look into the sources of NettyJaxrsServerand related classes, Reasteasy uses its own abstraction for http requests that do not implement HttpServletRequest.
If I change my implementation to use these abstractions, I can access request and response in my resource.
import org.jboss.resteasy.spi.HttpRequest;
import org.jboss.resteasy.spi.HttpResponse;
#GET
#Path("/")
public void example(#Context HttpResponse response,
#Context HttpRequest request) { ... }
This is not perfect, because it makes my resources depend on Resteasy interfaces but I decided to go with it for now to support mock testing of multipart data.
I'm trying to invoke a spring web service, using below url in browser the service "myservice" should return XML, ie based on the #RequestMapping annotations is the below URL correct?
> http://localhost:8080/mywebapp/myservice/feeds/allFeeds.xml/
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
#Controller
#RequestMapping("myservice")
public class TheController {
private TheService TheServiceWS;
public TheController(TheService TheServiceWS) {
this.TheServiceWS = TheServiceWS;
}
#RequestMapping(value = "feeds/allFeeds.xml", produces = MediaType.APPLICATION_XML_VALUE)
#ResponseBody
public String getValues() {
return TheServiceWS.getAllFeeds();
}
}
The problem for me was :
The #RequestMapping annotation value "myservice" was incorrect
should have been "mywebservice"
If the web service return as XML, it is the original the SOAP web service. In this case, you couldn't build the web service with #RequestMapping. The #RequestMapping is used when you want to build a REST web service.
In this case, you should use the Spring WS. You have to annotate the class with #Endpoint to create an web service endpoint. In the this endpoint, you create your request mapping with #Payloadroot. Please refer to this