Skip to main content

Jesey writing an authentication filter

It seems there are two ways to add authentication to Jersey REST apis

1) You can add a servlet filter.
public class RestAuthenticationFilter implements Filter {
    @Override
    public void destroy() {
        // TODO Auto-generated method stub        
    }
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {     
    try {
           User user = BasicAuthHelper.authenticateUser(request);
            if (user == null) {
                response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
            } else {
                request.setAttribute("user", user);
                chain.doFilter(request, response);
            }
     } catch (ApplicationException e) {
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.getMessage());
     }
    }
    @Override
    public void init(FilterConfig config) throws ServletException {
    } 
} 


2) You can do it using the jersey filter. You have to implement a ResourceFilterFactory and handle the auth in ContainerRequestFilter. The detailed code is below.  I like the approach 1 as it give complete lifecycle control. However if you need more specifc things like accessing QueryParams or PathParams then approach 2 is the way to go


public class RestAuthFilterFactory implements ResourceFilterFactory {
    private static final AppLogger logger = AppLogger
            .getLogger(RestAuthFilterFactory.class);

    @Context
    private UriInfo uriInfo;

    @Override
    public List create(AbstractMethod method) {
        return Collections.singletonList((ResourceFilter) new Filter());
    }

    private class Filter implements ResourceFilter, ContainerRequestFilter {
        protected Filter() {
        }

        public ContainerRequestFilter getRequestFilter() {
            return this;
        }

        public ContainerResponseFilter getResponseFilter() {
            return null;
        }

        public ContainerRequest filter(ContainerRequest request) {
            logger.info("Url invoked is {}", uriInfo.getPath());
            String authHeader = request.getHeaderValue("Authorization");
            if (authHeader != null && authHeader.startsWith("Basic ")) {
                   User user = BasicAuthHelper.authenticateUser(request);
               if (user == null) {
                  throw new WebApplicationException(Response.Status.UNAUTHORIZED);
               }
            return request;
            }
              throw new WebApplicationException(Response.Status.UNAUTHORIZED);
        }
        }
}

Comments

  1. Thank you, your article save me :)

    ReplyDelete
  2. Do you have a complete code example of your approach which you can publish?

    ReplyDelete
    Replies
    1. John unfortunately the code has some internal details of the company I work for and I cant publish those. I would be though happy to answer any spefic questions you have.

      Delete
    2. Hi. How do you get session from ContainerRequest

      Delete
    3. You have to inject the httpServletRequest in your authfilterfactory and then get session from it.

      @Context
      private HttpServletRequest httpServletRequest;

      Delete
  3. Thanks for posting this article.It really saved my day. Also I have found this article here describe the usage of jersey resource filter .

    http://goo.gl/Pm7ls

    ReplyDelete
  4. what library need to be imported for BasicAuthHelper?

    ReplyDelete
  5. BasicAuthHelper is just a class written by me, the intent of the code was to just demonstrate the strucuture of writing a filter. Instead of BasicAuthHelper you can plug in your own class to authenticate the user.

    ReplyDelete
  6. Hi, thank you very much for sample code. May i question, why are you using new instance of Filter for each resource method? Are there some thread-safe issues here? Thank you very much in advance

    ReplyDelete
    Replies
    1. in this e.g. you could get away by reusing same filter but what if someone tomorrow comes and adds instance variables in the class then in that case there can be concurrency issues. so like ServletFilter even here I am creating a new instance.

      Delete
    2. Thank you very much for your response. Sorry for being so precise, but as far as i know there is only one instance of ServletFilter in JVM loaded (it's according to Servlet 2.4 Spec 6.2.1 https://jira.sakaiproject.org/secure/attachment/16135/servlet-2_4-fr-spec.pdf)
      therefore perhaps there is a request scope variable in jersey that contains invoked abstact method information. Once again thank you for your help

      Delete
    3. you dont really need to create a new instance for e.g. this url here the author is not create a new instance http://anismiles.wordpress.com/2012/03/02/securing-versioning-and-auditing-rest-jax-rs-jersey-apis/ of SecurityContextFilter in the factory. But I guess I had to use uriInfo that I was injecting in the factory and thats why I might have done it. I could have injected that in the filter also but not sure if its doable, will have to try it out.

      Delete

Post a Comment

Popular posts from this blog

RabbitMQ java clients for beginners

Here is a sample of a consumer and producer example for RabbitMQ. The steps are
Download ErlangDownload Rabbit MQ ServerDownload Rabbit MQ Java client jarsCompile and run the below two class and you are done.
This sample create a Durable Exchange, Queue and a Message. You will have to start the consumer first before you start the for the first time.

For more information on AMQP, Exchanges, Queues, read this excellent tutorial
http://blogs.digitar.com/jjww/2009/01/rabbits-and-warrens/

+++++++++++++++++RabbitMQProducer.java+++++++++++++++++++++++++++
import com.rabbitmq.client.Connection; import com.rabbitmq.client.Channel; import com.rabbitmq.client.*; public class RabbitMQProducer { public static void main(String []args) throws Exception { ConnectionFactory factory = new ConnectionFactory(); factory.setUsername("guest"); factory.setPassword("guest"); factory.setVirtualHost("/"); factory.setHost("127.0.0.1"); factory.setPort(5672); Conne…

What a rocky start to labor day weekend

Woke up by earthquake at 7:00 AM in morning and then couldn't get to sleep. I took a bath, made my tea and started checking emails and saw that after last night deployment three storage node out of 100s of nodes were running into Full GC. What was special about the 3 nodes was that each one was in a different Data centre but it was named same app02.  This got me curious I asked the node to be taken out of rotation and take a heap dump.  Yesterday night a new release has happened and I had upgraded spymemcached library version as new relic now natively supports instrumentation on it so it was a suspect. And the hunch was a bullseye, the heap dump clearly showed it taking 1.3G and full GCs were taking 6 sec but not claiming anything.



I have a quartz job in each jvm that takes a thread dump every 5 minutes and saves last 300 of them, checking few of them quickly showed a common thread among all 3 data centres. It seems there was a long running job that was trying to replicate pending…

Email slavery

It seems I have become an EmailSlave. The first half of the day is spent in just answering to emails. There are so many emails where I am copied but I need not be. There are many emails  where its a 1-2 page email and somewhere down someone says @KP please answer this.  So it seems daily my work schedule is:
Signin to newrelic and check anomalies for 15 min. Check emails related production exception report and yes there are a ton of these report daily. Need a better tool here as this model is not scalable. I need to reduce the incoming data at me to only see relevant data like what newrelic does. May be I need to create a webapp out of these emails.Check emails for next few minutes before team callsDo team callsThen again back to checking emails until a I have taken a best shot at answering everyone waiting for my reply.Attend team meetings on Tue/Thu
Being an architect and coder at heart I don't feel satisfied at end of the day if there is nothing tangible getting done at the end.…