Monday, 20 January 2014

Struts2 with Spring Security Example

Spring security is very good and interesting technology for addressing the complex web security issues. And integrating this with MVC based struts2 framework will be definitely help many people. So In this post I will tell the steps needed to implement Struts2 with Spring Security with some code example .

  •  Add this filter in web.xml




<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>
<dispatcher>FORWARD</dispatcher>
<dispatcher>REQUEST</dispatcher>
</filter-mapping>


  • Create the login page as follows,


<s:form action="authenticationFilter" method="post" id="homeLogin">
<s:textfield id="loginid" name="j_username" value="" theme="simple" />

<s:password id="pwd" name="j_password" value="" theme="simple" />

<s:submit value="Login" " />
</s:form>


  • Create springsecurity.xml and configure it in web.xml as follows


<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/classes/SpringBeans.xml,/WEB-INF/classes/springsecurity.xml
</param-value>
</context-param>


  • Now the request with the /authenticationFilter Should be processed by Spring security. So configure springsecurity.xml as follows.




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


<bean id="springSecurityFilterChain" class="org.springframework.security.web.FilterChainProxy" />
<security:http pattern="/home.jsp " security="none"/>

<security:http auto-config="false" use-expressions="true"
entry-point-ref="authenticationEntryPoint">

<security:headers>
<security:cache-control />
<security:content-type-options />
<security:hsts />
<security:frame-options />
<security:xss-protection />

</security:headers>

<security:session-management
invalid-session-url="/sessionTimeout.html" />


<security:custom-filter position="FORM_LOGIN_FILTER" ref="myFilter" />
<security:custom-filter ref="basicAuthenticationFilter" after="BASIC_AUTH_FILTER" />

<security:intercept-url pattern="/crossdomain.xml"
access="permitAll" />


<security:intercept-url pattern="/**"
access="isAuthenticated()" />

<security:remember-me />

<security:access-denied-handler
error-page="/notauthorised.jsp" />


</security:http>

<bean id="authenticationEntryPoint"
class="org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint">

<constructor-arg>
<map>
<entry key="hasHeader('User-Agent','Java')"
value-ref="basicAuthEntryPoint" />

</map>
</constructor-arg>
<property name="defaultEntryPoint" ref="LoginUrlAuthenticationEntryPoint"/>
</bean>

<bean id="basicAuthEntryPoint"class="org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint">
<property name="realmName" value="REST Realm" />
</bean>

<bean id="basicAuthenticationFilter"class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter">
<property name="authenticationManager" ref="authManager"/>
<property name="authenticationEntryPoint" ref="basicAuthEntryPoint" />
</bean>

<bean id="LoginUrlAuthenticationEntryPoint"
class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">

<property name="loginFormUrl" value="/e-learning" />
</bean>
<security:authentication-manager alias="authManager" erase-credentials="false">
<security:authentication-provider
user-service-ref="jdbcUserService" />


</security:authentication-manager>
<bean id="jdbcUserService"
class="org.springframework.security.core.userdetails.jdbc.JdbcDaoImpl">

<property name="dataSource" ref="dataSource" />
<property name="usersByUsernameQuery"
value="select username,password,flag AS ENABLED
from adm_usermaster where username=? " />

<property name="authoritiesByUsernameQuery"
value="select au.username, ar.rolename
from adm_usermaster au, adm_rolemaster ar where au.roleid= ar.roleid and au.username = ?"/>


</bean>

<bean id="myFilter" class="com.genral.security.SecurityFilter">
<property name="authenticationManager" ref="authManager" />
<property name="filterProcessesUrl" value="/authenticationFilter" />
<property name="authenticationFailureHandler" ref="failureHandler" />
<property name="authenticationSuccessHandler" ref="successHandler" />

</bean>

<bean id="successHandler"
class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">

<property name="defaultTargetUrl" value="/authentication" />
<property name="alwaysUseDefaultTargetUrl" value="true" />
</bean>

<bean id="failureHandler"
class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">

<property name="defaultFailureUrl" value="/error.jsp?login_error=1" />
</bean>

</beans>




So whenever the login page is submitted, authenticationFilter will be processed by spring security and it will call the  com.genral.security.SecurityFilter class.

This creates UsernamePasswordAuthenticationToken object with username and password. The authenticationManager.authenticate() uses the authManager declared  in configuration file and authenticates the user.


 SecurityFilter.java


package com.genral.security;

import java.io.IOException;

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

import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
/**
*
* @author Sivaranjani D
*
*/
public class SecurityFilter extends AbstractAuthenticationProcessingFilter {

private static final String DEFAULT_FILTER_PROCESSES_URL = "/authenticationFilter";
private static final String POST = "POST";

public SecurityFilter() {
super(DEFAULT_FILTER_PROCESSES_URL);
}


@Override
public Authentication attemptAuthentication(HttpServletRequest request,
HttpServletResponse response) throws AuthenticationException,
IOException, ServletException, BadCredentialsException {
Authentication authentication = new UsernamePasswordAuthenticationToken(
request.getParameter("j_username").toString(),
request.getParameter("j_password").toString());


authentication = getAuthenticationManager().authenticate(
authentication);


SecurityContextHolder.getContext().setAuthentication(authentication);
return authentication;


}

@Override
public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {
final HttpServletRequest request = (HttpServletRequest) req;
final HttpServletResponse
response = (HttpServletResponse) res;
if (request.getMethod().equals(POST)) {


// If the incoming request is a POST, then we send it up
// to the AbstractAuthenticationProcessingFilter.
super.doFilter(request, response, chain);
} else {


// If it's a GET, we ignore this request and send it
// to the next filter in the chain. In this case, that
// pretty much means the request will hit the /login
// controller which will process the request to show the
// login page.

super.doFilter(request, response, chain);
}
}
}

No comments:

Post a Comment