Interview Questions

Spring Security Configuration

This article provides details about configuring Spring Security in a Spring based Web application.

The following is the list of beans to be configured for Spring Security.

spring-security.xml

<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"
        xsi:schemaLocation="http://www.springframework.org/schema/beans ...">

        <!-- List of filters to be executed before processing any HTTP request for client/browser -->
        <!-- A custom implementation of filters can be provided to provide additional functionality -->
        <beans:bean id="filterChainProxy"
                class="org.springframework.security.web.FilterChainProxy">
                <filter-chain-map path-type="ant">
                        <filter-chain pattern="/index.jsp" filters="none" />
                        <filter-chain pattern="/login.jsp" filters="none" />
                        <filter-chain pattern="/logout.jsp*" filters="none" />
                        <filter-chain pattern="/**/*" filters="concurrentSessionFilter, securityContextPersistenceFilter, logoutFilter, authenticationFilter, securityRequestFilter, exceptionTranslationFilter, filterSecurityInterceptor" />
                </filter-chain-map>
        </beans:bean>

        <beans:bean id="concurrentSessionFilter"
                class="org.springframework.security.web.session.ConcurrentSessionFilter">
                <beans:property name="sessionRegistry" ref="sessionRegistry" />
                <beans:property name="expiredUrl" value="/login.jsp" />
        </beans:bean>
       
        <beans:bean id="sessionRegistry"
                class="org.springframework.security.core.session.SessionRegistryImpl" />

        <beans:bean id="securityContextPersistenceFilter"
                class="org.springframework.security.web.context.SecurityContextPersistenceFilter" />

        <beans:bean id="logoutFilter"
                class="org.springframework.security.web.authentication.logout.LogoutFilter">
                <beans:constructor-arg value="/logout.jsp" />
                <beans:constructor-arg>
                        <beans:list>
                                <beans:bean
                                        class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
                        </beans:list>
                </beans:constructor-arg>
        </beans:bean>

        <authentication-manager alias="authenticationManager">
                <authentication-provider ref="daoAuthenticationProvider" />
        </authentication-manager>

        <beans:bean id="daoAuthenticationProvider"
                class="org.springframework.security.authentication.dao.DaoAuthenticationProvider">
                <beans:property name="userDetailsService" ref="userManager" />
                <beans:property name="passwordEncoder" ref="passwordEncoder" />
        </beans:bean>

        <beans:bean id="authenticationFilter"
                class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
                <beans:property name="authenticationManager" ref="authenticationManager" />
                <beans:property name="authenticationSuccessHandler"
                        ref="loginSuccessHandler" />
                <beans:property name="authenticationFailureHandler"
                        ref="loginFailureHandler" />
                <beans:property name="filterProcessesUrl" value="/j_spring_security_check" />
        </beans:bean>

        <beans:bean id="securityRequestFilter"
                class="org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter" />
        <beans:bean id="authenticationProcessingFilterEntryPoint"
                class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
                <beans:property name="loginFormUrl" value="/login.jsp" />
                <beans:property name="forceHttps" value="false" />
        </beans:bean>

        <beans:bean id="exceptionTranslationFilter"
                class="org.springframework.security.web.access.ExceptionTranslationFilter">
                <beans:property name="authenticationEntryPoint"
                        ref="authenticationProcessingFilterEntryPoint" />
                <beans:property name="accessDeniedHandler">
                        <beans:bean
                                class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
                                <beans:property name="errorPage" value="/accessDenied.jsp" />
                        </beans:bean>
                </beans:property>
        </beans:bean>

        <beans:bean id="loginSuccessHandler"
                class="org.springframework.security.web.authentication.SimpleUrlAuthenticationSuccessHandler">
                <beans:property name="defaultTargetUrl" value="/" />
        </beans:bean>
        <beans:bean id="loginFailureHandler"
                class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
                <beans:property name="defaultFailureUrl" value="/login.jsp?login_error=1" />
        </beans:bean>

        <beans:bean id="anonymousAuthenticationProvider"
                class="org.springframework.security.authentication.AnonymousAuthenticationProvider">
                <beans:property name="key" value="anonymous,ROLE_ANONYMOUS" />
        </beans:bean>

        <!-- An implementation of org.springframework.security.core.userdetails.UserDetailsService interface -->
        <beans:bean id="userManager" class="in.techdive.service.impl.UserManagerImpl" />

        <!-- Spring's support class for MD5 password encoder -->
        <beans:bean id="passwordEncoder"
                class="org.springframework.security.authentication.encoding.Md5PasswordEncoder" />

        <beans:bean id="accessDecisionManager"
                class="org.springframework.security.access.vote.AffirmativeBased">
                <beans:property name="decisionVoters">
                        <beans:list>
                                <beans:ref bean="authenticatedVoter" />
                        </beans:list>
                </beans:property>
        </beans:bean>

        <beans:bean id="authenticatedVoter"
                class="org.springframework.security.access.vote.AuthenticatedVoter">
        </beans:bean>

</beans:beans>

The bean with id "filterChainProxy" consist of a list of filters to be processed , before handling any HTTP request from client. Spring security framework provides basic functionality for all the filters.

Developers can extend those api's to provide custom functionality as per their requirement.

Three basic things which need to be taken care by the developer to make use of the above configurations are
1. Creating login/logout.jsp
2. Creating an implementation of UserDetailsService, which provides user details for the given userName.
3. Creating accessDenied.jsp for handling error/exception

Have a look at the login.jsp

<html>
    <head>
        <title>Login</title>
        </head>
       
        <body>
        <form method="post" id="loginForm" action="<c:url value="/j_security_check"/>" >
                <table width="50%"  border="0" cellspacing="4" cellpadding="8" >
                 <tr>
                        <td>
                               <label for="j_username"  >
                                   Username: <span class="req">*</span>
                                </label>
                        </td>
                       
                        <td>
                                <input type="text"  name="j_username" id="j_username" />
                        </td>
                </tr>
               
                <tr>
                        <td>
                                <label for="j_password" >
                                   Password: <span class="req">*</span>
                                </label>
                        </td>

                        <td>
                                <input type="password" class="text medium" name="j_password" id="j_password" tabindex="2" />
                        </td>
                </tr>

                <tr>
                        <td colspan="2" align="center">
                                 <input name="submit" value="login" type="submit" class="button" />
                        </td>
                 </tr>
        </table>
        </form>
       
    </body>
</html>

The names of username and password fields should be "j_username", j_password" respectively.

The action name of the form should be as "<c:url value="/j_security_check"/>"

Have a look at the deployment descriptor

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/javaee ...">

<context-param>
                <param-name>contextConfigLocation</param-name>
                <param-value>
            /WEB-INF/classes/spring-conf/spring-*.xml
        </param-value>
        </context-param>
        <listener>
                <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
        </listener>

        <filter>
                <filter-name>filterChainProxy</filter-name>
                <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
                <init-param>
                        <param-name>targetClass</param-name>
                        <param-value>
                                org.springframework.security.web.FilterChainProxy
                        </param-value>
                </init-param>
        </filter>

<filter-mapping>
                <filter-name>filterChainProxy</filter-name>
                <url-pattern>/*</url-pattern>

        </filter-mapping>

        <servlet>
                <servlet-name>dispatcher</servlet-name>
                <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
                <init-param>
                        <param-name>contextConfigLocation</param-name>
                        <param-value>/WEB-INF/classes/spring-servlet.xml</param-value>
                </init-param>
                <load-on-startup>1</load-on-startup>
        </servlet>

        <servlet-mapping>
                <servlet-name>dispatcher</servlet-name>
                <url-pattern>*.htm</url-pattern>
        </servlet-mapping>

        <session-config>
                <session-timeout>20</session-timeout>
        </session-config>

        <welcome-file-list>
                <welcome-file>index.jsp</welcome-file>
        </welcome-file-list>
       
</web-app>

Having done the above configurations, your application is secure and can be accessed only using log-in credentials.