I am currently developing a RESTful Webservice in Java using the Jersey library.
For security reasons, we want a custom authentication similar to Amazons Simple Storage Service. This requires, however, that I calculate an MD5 hash of the body (if there is any) to authenticate the request.
So far, I have used a custom Authenticator and Realm and plugged them into my context.
Upon trying to calculate the hash I first used the request itself resulting in an IllegalStateException, since the body can only be read once.
After investigating the problem I tried to wrap the request inside a HttpServletRequestWrapper but hasn't been successful so far.
I am basically using a wrapper like the one shown here:
http://forums.oracle.com/forums/thread.jspa?threadID=2156814&tstart=0
Inside my realm, where I do the authentication, I am first creating the wrapper like so:
MyRequestWrapper requestWrapper = new MyRequestWrapper(request);
then I am calculating the MD5 using the requestWrapper
and finally forwarding it
request.getRequestDispatcher("/*").forward(requestWrapper, response);
The processing works fine but I get an error like this after that:
Servlet.service() for servlet Jersey REST Service threw exception
java.lang.IllegalStateException
at org.apache.catalina.connector.ResponseFacade.sendError(ResponseFacade.java:407)
at com.sun.jersey.spi.container.servlet.WebComponent$Writer.finish(WebComponent.java:285)
at com.sun.jersey.spi.container.ContainerResponse.write(ContainerResponse.java:241)
Note that there is no mentioning of the getReader or getInputStream being called before (like I got without using any wrapper at all).
Now I am sure I am doing something wrong here but I really don't know much about this and would be really glad if someone could help me out here :)
Best Regards,
Lukas
As stated in my comment to my question:
I was accessing getReader() from the request. Response I did not touch. However I found that the problem was forwarding the wrapper. I didn't explicitly state this in my question but I am using tomcat and tried to use the above code inside a valve. I am still interested in the question if this is also possible from a valve, since this fits better into the tomcat model. I have now moved to using a filter which is not so nice, but works
I found however that this solution is quite nice (using a filter) instead of a tomcat valve.
Related
I just stumbled upon the fact that there are two classes that apparently do very similar things and it is not clear to me from the documentation when to use which.
ServletBearerExchangeFilterFunction and
ServerBearerExchangeFilterFunction
both live in the same package of Spring-Boot-Security-oauth2-resource-server and serve the same purpose of transporting a bearer token from the Context into outgoing http requests.
From the names I would have guessed that the Servlet option would be used for non Reactor projects while the Server version would be used with project Reactor. However that doesn't seem to be the case. At least the Servlet version seems to be working with Spring-WebFlux.
Can anyone please explain when to use which implementation?
We apparently had a false observation when using the ServletBearerExchangeFilterFunction. I corrected this in the original Question.
It turns out the ServletBearerExchangeFilterFunction can be used to configure a WebClient for use in a WebMVC (Thread based request processing) context while the ServerBearerExchangeFilterFunction works when using SpringWebFlux.
I am using jersey for REST service. I am deploying the REST service using apache tomcat. How do i set the session key in every response.
I have tried the below piece of code
return Response.ok(response.toString(), MediaType.APPLICATION_JSON).cookie(new NewCookie("JSESSIONID", request.getSession().getId())).build();
where request is instance of HttpServletRequest. I want to is there any configuration in web.xml so that the JSESSIONID is set for every response
Generally speaking (this holds true for many frameworks!) anything you want to be used in multiple places is best done with a filter. I'm not going to show you exactly how you do it, as it is very simple and it is better for you to read the docs, but have a look here:
https://jersey.java.net/documentation/latest/filters-and-interceptors.html
You can apply these to both methods and classes, so you only need to place annotations in a couple of places.
A very useful thing for writing clean code!
I'm trying to find a way to process HTTP requests programmatically with Tomcat 7 — "programmatically" meaning without actually making a TCP connection and sending the request. Basically, if I have an HttpServletRequest, is there a way to get Tomcat to give me the corresponding HttpServletResponse?
I perused http://tomcat.apache.org/tomcat-7.0-doc/index.html but couldn't find any mention of this now. One possibility is that HttpServlet has a method service() that would work, so if I could get a reference to the servlet object itself I'd be all set. Unfortunately, I can't find a way to get that either.
I should note that the servlet in question is a Jersey 1.17 servlet, although I don't think that matters to the question I'm asking. (Tomcat is clearly capable internally of dispatching a request based just on the URL, which is basically what I'm after here.)
If I understand your question correctly, you want to forward a request to another servlet. Take a look at the RequestDispatcher class and its forward() method. Here are some explanations and examples.
I'm creating a restful web service using Resteasy. One thing I need to do is to secure the service using a standard HTTP auth request. The tricky part is that the service is multi-tenant and needs to use one of the path parameters to determine the security realm.
There are a lot of articles typical of this link which describe setting up a single-tenant service. What I can't find is what to configure, and what interfaces to implement to describe my own security which is based on a path parameter + the username in the HTTP authentication method.
I envision that prior to calling any of the application logic, tomcat/resteasy would call a SecurityProvider (or whatever) interface with the HttpServletRequest and have me either throw a 401 or return a SecurityContext that gets passed to the JAX-RS handlers. In that routine, I would inspect the path parameters, and make a determination based on parameter+username+password given in the Basic/Digest/Form.
Is there any such beast?
I thought I'd update this since there's bee little activity on this question.
It looks like there's no baked in feature to do what I envisioned, so instead I extended the RestEasy servlet and added the security checks in my override before passing control back to the stock RestEasy servlet.
Seems to work well.
I'm trying to find a simple, flexible way to add JaaS authentication to REST. I found a post that I think leads me in the right direction (See StevenC's answer). It sounds like the servlet container is responsible for security, not the Jersey code itself. I like this idea, but need a little guidance on implementation.
Grizzly is my servlet container and I want to configure it to use JaaS for authentication. For now, a simple username/password combination would be fine, and hard-coding the username/password pairs directly in code is fine. As long as it uses JaaS, we can refine those details later.
As far as what is sent over HTTP, I'm thinking that storing a cookie would be the easiest way to make this all work. Whatever it takes to keep authentication junk away from my Jersey code.
Here's the code to start Grizzly so far:
final String baseUri = "http://localhost:9998/";
final Map initParams = new HashMap();
initParams.put("com.sun.jersey.config.property.packages",
"my.jersey.Service");
System.out.println("Starting grizzly...");
SelectorThread threadSelector = GrizzlyWebContainerFactory.create(baseUri, initParams);
System.out.println(String.format(
"Jersey app started with WADL available at %sapplication.wadl\n"
+ "Try out %shelloworld\nHit enter to stop it...", baseUri, baseUri));
System.in.read();
threadSelector.stopEndpoint();
System.exit(0);
If this whole process works, what's the best way to check permissions for the user? I would probably want my REST code to actually validate permissions at certain points. Am I even on the right track? Is there an easier way? A link to a tutorial would be a great answer. Even an answer like "I did that and it worked" would give me a warm fuzzy that I'm heading in the right direction.
Thanks for any help.
EDIT: Some clarifications for StevenC's comment:
Do you still want to use servlet filters to protect your resources? I'll use whatever can separate out the authentication detail from the Jersey code. It doesn't have to be servlet filters.
What is mean by "configure it to use JaaS"? The original plan was to protect the current API using JaaS. The next phase would be to make the entire API available online. It seemed to make sense to have a Jersey wrapper around the API calls, but keep authentication handled by Grizzly. Grizzly would have to interact with JaaS at that point I believe.
Are you thinking there should be some config that simply causes grizzly to protect your resources? I was considering a two-step process of authenticating the user and based on roles, authorizing the user to access resources. The idea was to have Grizzly handle authentication (using JaaS) and Jersey handle authorization.
"I don't see the need for the usage of cookies with a RESTful resource." It would be wonderful to remove the use of cookies, but how can the be accomplished? The system needs to know if the user is authenticated. I'd rather not ask them to pass a username/password/etc for each call. Even passing a session token as a parameter with every call seems "ugly".
Also, please note that I'm fairly new to REST. I've been doing SOAP for a couple of years, so I may have a "SOAP bias" that may be blinding me from some obvious, simple solution that everyone uses. If there's an easier way, please feel free to share. I'm just trying to learn as much as possible.
I'm not entirely clear what is meant by "configure it to use JaaS for authentication". If there's a simple configuration to have grizzly enforce HTTP authentication protecting URLs, I don't know about it.
I'm assuming from the other question and answer you reference that you want to use a servlet filter. Normally that's configured in the web.xml file of a servlet project. Grizzly is of course often used to start up a server from code as opposed to application config. When I used grizzly in this way I noticed that GrizzlyWebContainerFactory didn't offer any versions of create() that allowed you to specify servlet filters. However I did notice ServletAdapter [1] in the same project that does give you that ability.
As for the filter itself, I unfortunately don't know of a pre-built servlet filter that simply plugs JaaS configured login modules into your application, so you'll likely have to write a bit of code there. It's not much though, just choose the HTTP based authentication method (e.g. HTTP BASIC, DIGEST, etc.), extract credentials from the request accordingly, and login using the JaaS framework. I don't see that a cookie would specifically be needed for RESTful resources. The RESTful architectural style frowns upon keeping sessions. There are plenty of tutorials about JaaS otherwise, so I won't elaborate on that here.
Once a JaaS subject is active (consumer successfully logged in) you can simply get the current subject and check the active principals and credentials using the Subject.getSubject method.
Anyway, this answer is specifically to give a bit more of the details around doing auth with servlet filters, as you requested in the other (linked) question. This isn't necessarily the only way to do auth in a jersey webapp, but it's a fairly straightforward way to do it. I like it because it keeps me from injecting repetitive auth code in each resource that needs it.
[1] https://grizzly.dev.java.net/nonav/apidocs/com/sun/grizzly/http/servlet/ServletAdapter.html
Not sure if you are asking how to secure each resource, but I found a presentation on javapassion that sounds like what you are looking for. He says to use #Context SecurityContext as a parameter.
#Path("basket")
// Sub-resource locator could return a different resource if a user
// is a preferred customer:
public ShoppingBasketResource get(#Context SecurityContext sc) {
if (sc.isUserInRole("PreferredCustomer") {
return new PreferredCustomerShoppingBaskestResource();
} else {
return new ShoppingBasketResource();
}
}