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

Killing a particular Tomcat thread

Update: This JSP does not work on a thread that is inside some native code.  On many occasions I had a thread stuck in JNI code and it wont work. Also in some cases thread.stop can cause jvm to hang. According to javadocs " This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked". I have used it only in some rare occasions where I wanted to avoid a system shutdown and in some cases we ended up doing system shutdown as jvm was hung so I had a 70-80% success with it.   -------------------------------------------------------------------------------------------------------------------------- We had an interesting requirement. A tomcat thread that was spawned from an ExecutorService ThreadPool had gone Rogue and was causing lots of disk churning issues. We cant bring down the production server as that would involve downtime. Killing this thread was harmless but how to kill it, t

Adding Jitter to cache layer

Thundering herd is an issue common to webapp that rely on heavy caching where if lots of items expire at the same time due to a server restart or temporal event, then suddenly lots of calls will go to database at same time. This can even bring down the database in extreme cases. I wont go into much detail but the app need to do two things solve this issue. 1) Add consistent hashing to cache layer : This way when a memcache server is added/removed from the pool, entire cache is not invalidated.  We use memcahe from both python and Java layer and I still have to find a consistent caching solution that is portable across both languages. hash_ring and spymemcached both use different points for server so need to read/test more. 2) Add a jitter to cache or randomise the expiry time: We expire long term cache  records every 8 hours after that key was added and short term cache expiry is 2 hours. As our customers usually comes to work in morning and access the cloud file server it can happe

Preparing for an interview after being employed 11 years at a startup

I would say I didn't prepared a hell lot but  I did 2 hours in night every day and every weekend around 8 hours for 2-3 months. I did 20-30 leetcode medium problems from this list https://leetcode.com/explore/interview/card/top-interview-questions-medium/.  I watched the first 12 videos of Lecture Videos | Introduction to Algorithms | Electrical Engineering and Computer Science | MIT OpenCourseWare I did this course https://www.educative.io/courses/grokking-the-system-design-interview I researched on topics from https://www.educative.io/courses/java-multithreading-for-senior-engineering-interviews and leetcode had around 10 multithreading questions so I did those I watched some 10-20 videos from this channel https://www.youtube.com/channel/UCn1XnDWhsLS5URXTi5wtFTA