Wednesday, 23 September 2015

Jersey 2 authentication using ContainerRequestFilter

In previous post, I explained basic authentication using simple servlet filter. In this post, I am going to explain authenticating user using ContainerRequestFilter.

Define custom filter by implementing ContainerRequestFilter interface
First we need to define custom filter by implementing ‘javax.ws.rs.container.ContainerRequestFilter’ interface. All the container request filters must implement ContainerRequestFilter class. Request filter is executed before the resource method is run and before the response is created.

We must annotate the filter class that implements ContainerRequestFilte interface with @Provider annotation, so that the JAX-RS runtime will discover this filter.

Categories of filters
There are two variant of filters.
          a. Pre-matching filters
          b. post-matching filters
          
Pre-matching filters
Pre-matching filters execute before the request matching is started. Request matching is the process of identifying a resource method for given request. Annotate a filter class with @PreMatching annotation to make it as Pre-matching filter.

post-matching filters
post-matching filters applied  after a resource method has been selected to process the request (after request matching happens). Since these filter are applied after matching a resource method, these won't impact resource method matching process. By default all filters are post-matching filters.

Following step-by-step procedure explains complete working application.

Step 1: Create new dynamic web project ‘jersey_authentication’ in eclipse.

File -> New -> Dynamic Web Project

Give the project name as ‘jersey_authentication’, Press Next.

Select the check box ‘Generate web.xml deployment descriptor’, press Finish.


Step 2: Convert this project to maven project.
Right click on the project -> Configure -> Convert to Maven Project.

Total project structure looks like below.


Step 3: Update web.xml like below.

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
 id="WebApp_ID" version="3.0">
 <display-name>jersey_authentication</display-name>
 <welcome-file-list>
  <welcome-file>index.html</welcome-file>
  <welcome-file>index.htm</welcome-file>
  <welcome-file>index.jsp</welcome-file>
  <welcome-file>default.html</welcome-file>
  <welcome-file>default.htm</welcome-file>
  <welcome-file>default.jsp</welcome-file>
 </welcome-file-list>

 <servlet>
  <servlet-name>Jersey REST Service</servlet-name>
  <servlet-class>org.glassfish.jersey.servlet.ServletContainer</servlet-class>
  <init-param>
   <param-name>jersey.config.server.provider.packages</param-name>
   <param-value>com.self_learn</param-value>
  </init-param>
  <load-on-startup>1</load-on-startup>
 </servlet>

 <servlet-mapping>
  <servlet-name>Jersey REST Service</servlet-name>
  <url-pattern>/rest/*</url-pattern>
 </servlet-mapping>

</web-app>

Step 4: Update pom.xml for dependencies.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>jersey_authentication</groupId>
 <artifactId>jersey_authentication</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <packaging>war</packaging>
 <build>
  <sourceDirectory>src</sourceDirectory>
  <plugins>
   <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <configuration>
     <source>1.8</source>
     <target>1.8</target>
    </configuration>
   </plugin>
   <plugin>
    <artifactId>maven-war-plugin</artifactId>
    <version>2.4</version>
    <configuration>
     <warSourceDirectory>WebContent</warSourceDirectory>
     <failOnMissingWebXml>false</failOnMissingWebXml>
    </configuration>
   </plugin>
  </plugins>
 </build>

 <dependencies>
  <dependency>
   <groupId>org.glassfish.jersey.containers</groupId>
   <artifactId>jersey-container-servlet-core</artifactId>
   <version>2.21</version>
  </dependency>

  <dependency>
   <groupId>org.glassfish.jersey.core</groupId>
   <artifactId>jersey-server</artifactId>
   <version>2.21</version>
  </dependency>

 </dependencies>
</project>


Step 5: Create a package com.self_learn.filter, define class AuthFilter.

package com.self_learn.filter;

import java.io.IOException;

import javax.ws.rs.WebApplicationException;
import javax.ws.rs.container.ContainerRequestContext;
import javax.ws.rs.container.ContainerRequestFilter;
import javax.ws.rs.core.Response.Status;
import javax.ws.rs.ext.Provider;

@Provider
public class AuthFilter implements ContainerRequestFilter {

 @Override
 public void filter(ContainerRequestContext requestContext)
   throws IOException {
  String username = requestContext.getHeaderString("username");
  String password = requestContext.getHeaderString("password");

  if (!("admin".equals(username) && "admin".equals(password))) {
   throw new WebApplicationException(Status.UNAUTHORIZED);
  }

 }

}


‘filter’ method verifies the headers for 'username', 'password'. If both the headers has value 'admin', then request succeed, else client get response status '401 Unauthorized'

Step 6: Create a package 'com.self_learn.resource', define class HelloWorld.

package com.self_learn.resource;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Path("/hello")
public class HelloWorld {

 @GET
 @Produces(MediaType.TEXT_PLAIN)
 public String message() {
  return "Hello World !";
 }

}


Complete project structure looke like below.

Run the application on server. To demonstrate this application, I am going to use ‘Advanced Rest client’ plugin of Chrome browser.

Open Advanced Rest client and use following url.

Set following headers.
username: admin
password: admin

Submit the request by setting above headers, you will get following kind of response.

Submit the request by setting wrong headers, you will get following kind of response.





Prevoius                                                 Next                                                 Home

No comments:

Post a Comment