12

I am working on a WebService using JAX-RS/Jersey.

I've set up a ContainerRequestFilter whose purpose is to authenticate the user. I only need to protect some of the paths with authentication, the rest can be available to everyone.

I want to retrieve matchedResources / matchedResults via ExtendedUriInfo in my ContainerRequestFilter so that I can check if the path should be protected or not. Is there a way to create a filter which is invoked after ExtendedUriInfo is populated, but before the matched resource class and method is invoked?

John B
  • 195
  • 1
  • 9
  • Sounds like you're reinventing a bit of Java EE! If you don't have an EJB sitting behind your web-service, consider adding one. You'll be able to annotate with roles as you please. – Richard Sitze Aug 04 '12 at 21:26
  • Thanks for the suggestion Richard. I haven't looked in to Roles all that much yet, but I had the impression Roles worked only with an *auth-method* configured. I have a *login* method, and after the user logs in he/she communicates with the WebService using an accessToken + userId pair. – John B Aug 04 '12 at 21:50
  • Admittedly my experience with authentication via web-services is weak. I do know that via the servlet interface there is an API available to log a user in - side stepping the auth-method. In short, servlets can "code their own" authentication method. I'd always assumed there was such for web-services as well. – Richard Sitze Aug 04 '12 at 22:15
  • Since you're using a filter, that mechanism should be available to you: see http://docs.oracle.com/javaee/6/api/javax/servlet/http/HttpServletRequest.html#login(java.lang.String, java.lang.String) – Richard Sitze Aug 04 '12 at 22:27

3 Answers3

10

Here is a more general answer (for instance if you're using another jax-rs implementation like CXF):

Just add the following in your filter class as an instance variable:

@Context

ResourceInfo info;

"javax.ws.rs.container.ResourceInfo is a new JAX-RS context which can be injected into filters and interceptors and checked which resource class and method are about to be invoked."

(source : https://cwiki.apache.org/confluence/display/CXF20DOC/JAX-RS+Basics#JAX-RSBasics-ResourceInfo)

Original answer here

Community
  • 1
  • 1
Kevin L.
  • 316
  • 1
  • 3
  • 8
5

Found a way to do it with ContainerRequestFilter:

public void filter(ContainerRequestContext requestContext) {
    UriRoutingContext routingContext = (UriRoutingContext) requestContext.getUriInfo();
    ResourceMethodInvoker invoker = (ResourceMethodInvoker) routingContext.getInflector();
    Class<?> className = invoker.getResourceClass();
    Method methodName = invoker.getResourceMethod();
}
Arthur
  • 1,484
  • 1
  • 16
  • 18
3

I managed to figure it out.

The approach I have found to work is to abandon doing this in the ContainerRequestFilter and create a ResourceFilterFactory instead. In the ResourceFilterFactory I can use

AbstractMethod.isAnnotationPresent(clazz)

to determine if my custom annotation is present. If my annotation is present, I can then return a list containing my AuthenticationContainerRequestFilter.

Another tip for anyone reading this answer is that injection in the ContainerRequestFilter will not work when using the ResourceFilterFactory approach. What I did was to do any injection in the ResourceFilterFactory and then pass the injected objects to the ContainerRequestFilter via its constructor.

John B
  • 195
  • 1
  • 9