Tuesday, 19 May 2015

Spring Security - Pre-Authentication using Header

In our earlier tutorial we have seen about Spring Security Pre-Authentication using request parameters. In this tutorial we will see about Pre-Authentication by setting header value. For more docs please refer to Spring Docs link.

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/maven-v4_0_0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>com.app.mvc</groupId>
 <artifactId>springsecurity</artifactId>
 <packaging>war</packaging>
 <version>1.0-SNAPSHOT</version>
 <name>Spring Security</name>
 <url>http://maven.apache.org</url>
 <properties>
  <spring.version>3.0.5.RELEASE</spring.version>
  <jackson-mapper-asl.version>1.9.9</jackson-mapper-asl.version>
  <jaxb-api.version>2.2.7</jaxb-api.version>
 </properties>
 <dependencies>
  <dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>3.8.1</version>
   <scope>test</scope>
  </dependency>
  <!-- Spring 3 dependencies -->
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
   <version>${spring.version}</version>
   <scope>compile</scope>
  </dependency>

  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-web</artifactId>
   <version>${spring.version}</version>
   <scope>compile</scope>
  </dependency>

  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-webmvc</artifactId>
   <version>${spring.version}</version>
   <scope>compile</scope>
  </dependency>

  <!-- Spring Security -->
  <dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-core</artifactId>
   <version>${spring.version}</version>
   <type>jar</type>
   <scope>compile</scope>
  </dependency>
  <dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-web</artifactId>
   <version>${spring.version}</version>
   <type>jar</type>
   <scope>compile</scope>
  </dependency>
  <dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-config</artifactId>
   <version>${spring.version}</version>
   <type>jar</type>
   <scope>compile</scope>
  </dependency>
  <dependency>
   <groupId>org.springframework.security</groupId>
   <artifactId>spring-security-taglibs</artifactId>
   <version>${spring.version}</version>
   <type>jar</type>
   <scope>compile</scope>
  </dependency>

  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>jstl</artifactId>
   <version>1.2</version>
   <scope>compile</scope>
  </dependency>

  <dependency>
   <groupId>taglibs</groupId>
   <artifactId>standard</artifactId>
   <version>1.1.2</version>
   <scope>compile</scope>
  </dependency>

  <dependency>
   <groupId>org.codehaus.jackson</groupId>
   <artifactId>jackson-mapper-asl</artifactId>
   <version>${jackson-mapper-asl.version}</version>
   <scope>compile</scope>
  </dependency>

  <dependency>
   <groupId>javax.xml.bind</groupId>
   <artifactId>jaxb-api</artifactId>
   <version>${jaxb-api.version}</version>
   <scope>compile</scope>
  </dependency>

  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>3.0.1</version>
   <scope>provided</scope>
  </dependency>

 </dependencies>
 <build>
  <finalName>springsecurity</finalName>
 </build>
</project>


web.xml


<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>

 <display-name>Spring Security</display-name>

 <context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>/WEB-INF/spring-mvc-servlet.xml</param-value>
 </context-param>

 <filter>
  <filter-name>springSecurityFilterChain</filter-name>
  <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
 </filter>
 <filter-mapping>
  <filter-name>springSecurityFilterChain</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>

 <listener>
  <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
 </listener>

 <servlet>
  <servlet-name>spring-mvc</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <load-on-startup>1</load-on-startup>
 </servlet>

 <servlet-mapping>
  <servlet-name>spring-mvc</servlet-name>
  <url-pattern>/*</url-pattern>
 </servlet-mapping>


</web-app>


spring-mvc-servlet.xml


<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:security="http://www.springframework.org/schema/security"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
     
     <!-- Annotation are configuring the application -->
     <mvc:annotation-driven/>
 
     <!-- Scan this package for all config annotations -->
 <context:component-scan base-package="com.app.controller" />
 
 <security:http use-expressions="true" auto-config="true" entry-point-ref="http403EntryPoint">
     <!-- Additional http configuration omitted -->
     <security:intercept-url pattern="/**" access="hasRole('ROLE_USER')" />
     <security:custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />
   </security:http>

    <bean id="siteminderFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">
     <property name="principalRequestHeader" value="SM_USER"/>
     <property name="authenticationManager" ref="authenticationManager" />
 </bean>
 
   <bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">
     <property name="preAuthenticatedUserDetailsService">
        <bean id="userDetailsServiceWrapper"  class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
          <property name="userDetailsService" ref="customUserDetailsService"/>
        </bean>
     </property>
    </bean>

    <security:authentication-manager alias="authenticationManager">
       <security:authentication-provider ref="preauthAuthProvider" />
    </security:authentication-manager> 
    
    <bean id="customUserDetailsService" class="com.app.service.CustomUserDetailsService"></bean>
    <bean id="http403EntryPoint" class="org.springframework.security.web.authentication.Http403ForbiddenEntryPoint"></bean>
    
</beans>


Employee.java


package com.app.model;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement(name="employee")
@XmlAccessorType(XmlAccessType.NONE)
public class Employee {
 
 @XmlElement(name="empid")
 private String empId;
 
 @XmlElement(name="firstname")
 private String firstName;
 
 @XmlElement(name="lastname")
 private String lastName;
 
 @XmlElement(name="designation")
 private String designation;
 
 public String getEmpId() {
  return empId;
 }
 public void setEmpId(String empId) {
  this.empId = empId;
 }
 public String getFirstName() {
  return firstName;
 }
 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }
 public String getLastName() {
  return lastName;
 }
 public void setLastName(String lastName) {
  this.lastName = lastName;
 }
 public String getDesignation() {
  return designation;
 }
 public void setDesignation(String designation) {
  this.designation = designation;
 } 
}


Employees.java


package com.app.model;

import java.util.Collection;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;


@XmlRootElement(name="employees")
@XmlAccessorType(XmlAccessType.NONE)
public class Employees 
{
 @XmlElement(name="employees")
 private Collection<Employee> employees;

 public Collection<Employee> getUsers() {
  return employees;
 }

 public void setUsers(Collection<Employee> employees) {
  this.employees = employees;
 }
}


CustomUserDetailsService.java


package com.app.service;

import java.util.ArrayList;
import java.util.Collection;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.GrantedAuthorityImpl;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;

public class CustomUserDetailsService implements UserDetailsService
{
 public UserDetails loadUserByUsername(String userName)
         throws UsernameNotFoundException
    {
  System.out.println("Username::: "+userName);
  UserDetails user = null;
  if(userName.equalsIgnoreCase("admin")){
   user = getAdminUser(userName);
  }else if(userName.equalsIgnoreCase("dba")){
   user = getDBAUser(userName);
  }else if(userName.equalsIgnoreCase("user")){
   user = getUserUser(userName);
  }
  
  if (user == null) {
         throw new UsernameNotFoundException("Invalid user : "+userName);
     }
  
  return user;
    }
 
 private UserDetails getAdminUser(String username) {
     Collection<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
     //Don't change the order
     grantedAuthorities.add(new GrantedAuthorityImpl("ROLE_ADMIN"));
     grantedAuthorities.add(new GrantedAuthorityImpl("ROLE_DBA"));
     grantedAuthorities.add(new GrantedAuthorityImpl("ROLE_USER"));
     
     return new User(username, "adminpassword", true, true, true, true,
             grantedAuthorities);
 }

 private UserDetails getDBAUser(String username) {
     Collection<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
     //Don't change the order
     grantedAuthorities.add(new GrantedAuthorityImpl("ROLE_DBA"));
     grantedAuthorities.add(new GrantedAuthorityImpl("ROLE_USER"));
     return new User(username, "dbapassword", true, true, true, true,
             grantedAuthorities);
 }

 private UserDetails getUserUser(String username) {
     Collection<GrantedAuthority> grantedAuthorities = new ArrayList<GrantedAuthority>();
     grantedAuthorities.add(new GrantedAuthorityImpl("ROLE_USER"));
     return new User(username, "userpassword", true, true, true, true,
             grantedAuthorities);
 }
}


EmployeeController.java


package com.app.controller;

import java.util.ArrayList;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.app.model.Employee;
import com.app.model.Employees;

@Controller
@RequestMapping("/employees")
public class EmployeeController 
{
 @RequestMapping(method = RequestMethod.GET,  headers="Accept=application/xml")
 public @ResponseBody Employees getAllUsers() 
 {
  
  String userRole = getUserRole();
  
  System.out.println("User Role : "+userRole);
        
  Employee emp1 = new Employee();
  
  if(userRole.equals("admin")){
   emp1.setEmpId("101");
   emp1.setFirstName("Steve");
   emp1.setLastName("Smith");
   emp1.setDesignation("ADMIN");
  
  }else if(userRole.equals("dba")){
   emp1.setEmpId("301");
   emp1.setFirstName("Bill");
   emp1.setLastName("Rock");
   emp1.setDesignation("DBA");
  
  }else if(userRole.equals("user")){
   emp1.setEmpId("163");
   emp1.setFirstName("Tim");
   emp1.setLastName("Jack");
   emp1.setDesignation("USER");
  } 
  
  Employees users = new Employees();
  users.setUsers(new ArrayList<Employee>());
  users.getUsers().add(emp1);
  
  return users;
 }
 
 
 private String getUserRole(){
  
  String userRole = "";
  
  SecurityContext context = SecurityContextHolder.getContext();
        Authentication authentication = context.getAuthentication();
        
        for (GrantedAuthority auth : authentication.getAuthorities()) {
            if ("ROLE_ADMIN".equals(auth.getAuthority())){
                userRole = "admin";
                return userRole;
            }
            if ("ROLE_DBA".equals(auth.getAuthority())){
                userRole = "dba";
                return userRole;
            }
            if ("ROLE_USER".equals(auth.getAuthority())){
                userRole = "user";
                return userRole;
            }
        }
        
        return userRole;
 }
}



OUTPUT:

Request without header value - Error page


spring_security_pre_auth_error









Request with SM_USER header - Success page

spring_security_pre_auth_success








No comments :

Post a Comment