Wednesday 23 September 2015

Jersey 2 HTTP basic Authentication

In this post, I am going to explain how to do HTTP basic authentication using filters (I am not using any jersey specific interceptors here, I will explain authentication using interceptors later).

I am going to forward all my requests to AuthFilter (custom filter), It check request headers (username, password) for validity. If username and password are correct, it allow access to REST services, else it reject access.

Following is the step-by-step procedure to build complete working application.

Step 1: Create new Dynamic web project “jersey_authentication” in Eclipse.

File -> New -> Dynamic Web Project

Press Next. Select the check box ‘Generate web.xml deployment descriptor’.


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: We need to forward our requests to a filter, which verifies the authentication credentials.

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>

 <filter>
  <filter-name>AuthenticationFilter</filter-name>
  <filter-class>com.self_learn.filters.AuthFilter</filter-class>
 </filter>

 <filter-mapping>
  <filter-name>AuthenticationFilter</filter-name>
  <url-pattern>/rest/*</url-pattern>
 </filter-mapping>
</web-app>

As you observe web.xml, I am forwarding all /rest/* requests to a filter ‘com.self_learn.filters.AuthFilter’, it performs authentication.

Step 4: Update pom.xml for maven 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>

  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>3.1.0</version>
  </dependency>

 </dependencies>
</project>


Step 5: Create package ‘com.self_learn.filters’. Define AuthFilter class, which validates user credentials.

package com.self_learn.filters;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.self_learn.service.AuthService;

public class AuthFilter implements javax.servlet.Filter {

 @Override
 public void doFilter(ServletRequest request, ServletResponse response,
   FilterChain filter) throws IOException, ServletException {
  if (request instanceof HttpServletRequest) {
   HttpServletRequest httpRequest = (HttpServletRequest) request;

   String username = httpRequest.getHeader("username");
   String password = httpRequest.getHeader("password");

   AuthService authService = new AuthService();

   boolean isAuthenticated = authService.authenticate(username,
     password);

   if (isAuthenticated) {
    filter.doFilter(request, response);
   } else {
    if (response instanceof HttpServletResponse) {
     HttpServletResponse httpResponse = (HttpServletResponse) response;
     httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
    }
   }
  }
 }

 @Override
 public void destroy() {
 }

 @Override
 public void init(FilterConfig arg0) throws ServletException {
 }
}


Step 6: Create package ‘com.self_learn.service’. Define class AuthService, which validates user credentials.

package com.self_learn.service;

public class AuthService {
 public boolean authenticate(String userName, String password) {

  if (userName == null || password == null)
   return false;

  if (userName.equals("admin") && password.equals("admin"))
   return true;
  return false;
 }
}


Step 7: Create package ‘com.self_learn.controller’. Define class HelloWorldController.

package com.self_learn.controller;

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

@Path("/helloworld")
public class HelloWorldController {

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

}


Total project structure looks like below.


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

Open ‘Advanced Rest client’

Update url as ‘http://localhost:8080/jersey_authentication/rest/helloworld’.

Add following headers
username: admin
password: admin

Submit the request, you will get following kind of output.

Submit the request using invalid credentials, you will get ‘401 Unauthorized’.



Prevoius                                                 Next                                                 Home

No comments:

Post a Comment