Interview Questions

Spring Security REST Web Service Authentication

Spring Security REST Web service Authentication

Here is the code sample to authenticate REST Web service using SPring Security framework.

spring-security.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
        xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xmlns:context="http://www.springframework.org/schema/context"
        xsi:schemaLocation="http://www.springframework.org/schema/beans <a href="http://www.springframework.org/schema/beans/spring-beans.xsd
" title="http://www.springframework.org/schema/beans/spring-beans.xsd
">http://www.springframework.org/schema/beans/spring-beans.xsd
</a>                        <a href="http://www.springframework.org/schema/security" title="http://www.springframework.org/schema/security">http://www.springframework.org/schema/security</a> <a href="http://www.springframework.org/schema/security/spring-security.xsd
" title="http://www.springframework.org/schema/security/spring-security.xsd
">http://www.springframework.org/schema/security/spring-security.xsd
</a>                        <a href="http://www.springframework.org/schema/context
" title="http://www.springframework.org/schema/context
">http://www.springframework.org/schema/context
</a>       <a href="http://www.springframework.org/schema/context/spring-context.xsd">

" title="http://www.springframework.org/schema/context/spring-context.xsd">

">http://www.springframework.org/schema/context/spring-context.xsd">

</a>    <global-method-security pre-post-annotations="enabled" />  
   
    <http pattern="/rest/login" security="none"/>  
    <http pattern="/rest/signup" security="none"/>

    <http  pattern="/rest/**" entry-point-ref="restAuthenticationEntryPoint" create-session="stateless">
         
        <custom-filter before="FORM_LOGIN_FILTER" ref="appAuthenticationFilter"/>
       
    </http>
       
    <authentication-manager alias="authenticationManager">
        <authentication-provider ref="appAuthenticationProvider" />
    </authentication-manager>
   
    <beans:bean id="appAuthenticationProvider"
                class="com.test.common.security.AppAuthenticationProvider">
               
        </beans:bean>
       
        <beans:bean id="appAuthenticationSuccessHandler"
                class="com.test.common.security.AppAuthenticationSuccessHandler">
               
        </beans:bean>
       
        <beans:bean id="restAuthenticationEntryPoint"
                class="com.test.common.security.RestAuthenticationEntryPoint">
                               
        </beans:bean>
       
       
         <beans:bean id="appAuthenticationFilter" class="com.test.common.security.AppAuthenticationFilter">  
        <beans:property name="authenticationManager" ref="authenticationManager" />
        <beans:property name="authenticationSuccessHandler" ref="appAuthenticationSuccessHandler" />  
    </beans:bean>
   
    </beans:beans>

AppAuthenticationFilter.java

package com.test.common.security;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.authentication.AuthenticationDetailsSourceImpl;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.stereotype.Component;


public class AppAuthenticationFilter  extends AbstractAuthenticationProcessingFilter {

    public AppAuthenticationFilter() {
        super("/**");
    }

    @Override
    protected boolean requiresAuthentication(HttpServletRequest request, HttpServletResponse response) {
        return true;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {

        String username = request.getHeader("username");
        String password = request.getHeader("password");
       
System.out.format("username %s,  password %s",username,password);
       

        UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(username,password);
        System.out.println("auth - > "+authentication);

        return getAuthenticationManager().authenticate(authentication);
    }

    @Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult)
            throws IOException, ServletException {
        super.successfulAuthentication(request, response, chain, authResult);

        // As this authentication is in HTTP header, after success we need to continue the request normally
        // and return the response as if the resource was not secured at all
        chain.doFilter(request, response);
    }
}

AppAuthenticationProvider.java

package com.test.common.security;

import java.util.Collection;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;

public class AppAuthenticationProvider extends AbstractUserDetailsAuthenticationProvider {
   
    public boolean supports(Class<?> authentication) {
        System.out.println("inside supportsr method");
        return true;
    }

    protected void additionalAuthenticationChecks(UserDetails userDetails, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
    }

    @Override
    protected UserDetails retrieveUser(String username, UsernamePasswordAuthenticationToken authentication) throws AuthenticationException {
       
        System.out.println("inside retrieveUser method");
       
        //UserDetails should be retrieved from a database or another datasource. For testing purpose its hardcoded here.
        UserDetails userDetails = new UserDetails() {
                       
                        @Override
                        public boolean isEnabled() {
                                // TODO Auto-generated method stub
                                return true;
                        }
                       
                        @Override
                        public boolean isCredentialsNonExpired() {
                                // TODO Auto-generated method stub
                                return true;
                        }
                       
                        @Override
                        public boolean isAccountNonLocked() {
                                // TODO Auto-generated method stub
                                return true;
                        }
                       
                        @Override
                        public boolean isAccountNonExpired() {
                                // TODO Auto-generated method stub
                                return true;
                        }
                       
                        @Override
                        public String getUsername() {
                                // TODO Auto-generated method stub
                                return "techdive";
                        }
                       
                        @Override
                        public String getPassword() {
                                // TODO Auto-generated method stub
                                return "password";
                        }
                       
                        @Override
                        public Collection<? extends GrantedAuthority> getAuthorities() {
                                // TODO Auto-generated method stub
                                return null;
                        }
                };
               
                if(authentication.getPrincipal().equals(userDetails.getUsername())
                        && (authentication.getCredentials().equals(userDetails.getPassword())))
                           System.out.println("authenticated");
                        else
                                throw new UsernameNotFoundException("user name not found");
               
               
        return userDetails;
    }

}

AppAuthenticationSuccessHandler.java

package com.test.common.security;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;


public class AppAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
        // We do not need to do anything extra on REST authentication success, because there is no page to redirect to
        System.out.println("Authentication Success");
    }

}

ExchangeController.java

package com.test.common.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.test.common.model.CurrencyExchangeRate;
import com.test.common.service.ExchangeService;

@Controller
@RequestMapping("/exchange")
public class ExchangeController {
       
        @Autowired
        ExchangeService exchangeService;

        @RequestMapping(value = "list", method = RequestMethod.GET)
        public @ResponseBody
        List<CurrencyExchangeRate> listExchangeRates() {

                return exchangeService.listExchangeRates();

        }
               
}

mvc-dispatcher-servlet.xml

<beans xmlns="http://www.springframework.org/schema/beans"
        xmlns:context="http://www.springframework.org/schema/context"
        xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       
        xsi:schemaLocation="
       <a href="http://www.springframework.org/schema/beans" title="http://www.springframework.org/schema/beans">
http://www.springframework.org/schema/beans</a>    
        <a href="http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
" title="http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
">
http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
</a>        <a href="http://www.springframework.org/schema/context" title="http://www.springframework.org/schema/context">http://www.springframework.org/schema/context</a>
        <a href="http://www.springframework.org/schema/context/spring-context-3.0.xsd
" title="http://www.springframework.org/schema/context/spring-context-3.0.xsd
">
http://www.springframework.org/schema/context/spring-context-3.0.xsd
</a>        <a href="http://www.springframework.org/schema/mvc
" title="http://www.springframework.org/schema/mvc
">
http://www.springframework.org/schema/mvc
</a>        <a href="http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
" title="http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
">
http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
</a>       ">

        <context:component-scan base-package="com.test.common" />

        <mvc:annotation-driven />
       
               
        <bean
                class="org.springframework.web.servlet.view.InternalResourceViewResolver">
                <property name="prefix" value="/WEB-INF/view/" />
                <property name="suffix" value=".jsp" />
        </bean>
       
         
</beans>

web.xml

<web-app id="WebApp_ID" version="2.4"
        xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
        <a href="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">


" title="http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

">http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

</a>    <display-name>Spring Web MVC Application</display-name>
<context-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>
                classpath:exchange-db.xml,
                                /WEB-INF/mvc-dispatcher-servlet.xml,
                                /WEB-INF/spring-security.xml
                </param-value>
        </context-param>
        <servlet>
                <servlet-name>mvc-dispatcher</servlet-name>
                <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
                <load-on-startup>1</load-on-startup>
        </servlet>

        <servlet-mapping>
                <servlet-name>mvc-dispatcher</servlet-name>
                <url-pattern>/rest/*</url-pattern>
        </servlet-mapping>
       
        <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>

</web-app>