Secure your web application with Spring Security

Spring Security is great framework to secure web application. It’s easy to configure and it doesn’t need to make special changes or deploy libraries to your Servlet or EJB container.

Spring security keeps your application objects free of security code, unless you specifically choose to interact with the security context.

   

Photo credit: V.Áron

This article explains how to secure a JEE application with Spring Security by a sample project. This project is implemented with JSF, Spring (version 3.0) and Hibernate.

The source code of the project is available on github here.

Basic configuration

In this part we will add dependencies and basic configuration to integrate Spring security to the web application.

  • Add Spring Security dependencies to the maven pom.xml file.
     <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>org.springframework.security.web</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>org.springframework.security.config</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>org.springframework.security.taglibs</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
    

– Update web.xml file.
Inside web.xml, insert the following block of code. It should be inserted right after the /context-param end-tag.

<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>

– Add applicationContext-security.xml file
This file contains the basic Spring Security config. There is no user access control for any path. Users are defined in the Spring application context file.

<?xml version="1.0" encoding="UTF-8"?>

<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:jdbc="http://www.springframework.org/schema/jdbc"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
		http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">
 
 <http use-expressions="true">
        <intercept-url pattern="/**" filters="none" />
        <form-login />
        <logout />
    </http>

	<authentication-manager>
	    <authentication-provider>
	      <user-service>
	        <user name="user1" password="password1" authorities="ROLE_USER, ROLE_ADMIN" />
	        <user name="user2" password="password2" authorities="ROLE_USER" />
	      </user-service>
	    </authentication-provider>
  </authentication-manager>
</beans>

After the basic configuration is done, you should have your web application running and you should access all pages.

Security Configuration

1 – Authentication

Authentication is the process of determining whether someone or something is, in fact, who or what it is declared to be. [2]

Spring security supports LDAP, database, XML and Properties file to authenticate users. In this article, we use database authentication. The database schema is created by hibernate and it is populated by DbUnit framework.

We create two persistent classes to save users and their authorities.


– Create a login.xhtml page as shown in the code bellow

<html xmlns:jsp="http://java.sun.com/JSP/Page"
      xmlns:h="http://java.sun.com/jsf/html"
      xmlns:f="http://java.sun.com/jsf/core"
      xmlns:c="http://java.sun.com/jstl/core" 
>
<head></head>
<body>

<c:if test="${param.state=='failure'}">
		<c:set var="username" value="#{sessionScope.SPRING_SECURITY_LAST_USERNAME}"/>
		<div class="ERROR">
			Your login attempt was not successful, try again.<br />
			Reason: #{sessionScope.SPRING_SECURITY_LAST_EXCEPTION.message}
		</div>
</c:if>
	<form  action="#{request.contextPath}/j_spring_security_check" method="post">
		<h:panelGrid columns="2" title="Customer">
			<f:facet name="header"> 
				<h:outputText value="Login form" />
			</f:facet>
			<h:outputText value="User:" />
			<h:inputText id="j_username" value="#{username}"  />
			<h:outputText value="Password:" />
			<h:inputSecret id="j_password" />
			<f:facet name="footer"> 
				<h:commandButton  value="Login" type="submit"  />
			</f:facet>
		</h:panelGrid>
	</form>
</body>
</html>

To add JDBC Spring security some changes nead to be done to the applicationContext-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"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
		http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd">

	<http use-expressions="true" access-denied-page="/pages/static/accessDenied.jsf">
		<intercept-url pattern="/login.jsf" filters="none"/>
		<intercept-url pattern="/pages/**" access="isAuthenticated()" />
		<form-login login-page="/login.jsf" default-target-url="/pages/static/welcome.jsf" authentication-failure-url="/login.jsf?state=failure"/>
		<logout logout-success-url="/login.jsf?state=logout"  />
	</http>

	<authentication-manager alias="authenticationManager">
		<authentication-provider>
			<password-encoder hash="md5" />
			<jdbc-user-service data-source-ref="dataSource"
				users-by-username-query="SELECT U.login AS username, U.password as password, U.enabled as enabled FROM user U where U.login=?"
				authorities-by-username-query="SELECT U.login as username, A.authority_name as authority FROM user U, authority A WHERE U.user_id=A.user_id and U.login=?"
				role-prefix="ROLE_" />
		</authentication-provider>
	</authentication-manager>

</beans:beans>

To maximize password security we made a choice to use md5 password encoding.

2 – Authorization

Authorization is the function of specifying access rights to resources, which is related to information security and computer security in general and to access control in particular. More formally, “to authorize” is to define access policy. [1]

With spring security we can manage pages, screen components and methods execution rights policies.

– Path access control

Then implement access rules for URLs by adding <intercept-url> children directly under the <http> element.

	
	<http use-expressions="true" access-denied-page="/pages/static/accessDenied.jsf">
		<intercept-url pattern="/login.jsf" filters="none" />
		<intercept-url pattern="/pages/static/**" access="isAuthenticated()" />
		<intercept-url pattern="/pages/customer/**" access="hasAnyRole('ROLE_ADMIN','ROLE_CUSTOMER')" />
		<intercept-url pattern="/pages/order/**" access="hasAnyRole('ROLE_ADMIN','ROLE_ORDER')" />
		<intercept-url pattern="/pages/admin/**" access="hasRole('ROLE_ADMIN')" />
		<form-login login-page="/login.jsf" default-target-url="/pages/static/welcome.jsf"
			authentication-failure-url="/login.jsf?state=failure" />
		<logout logout-success-url="/login.jsf?state=logout" />
	</http>

-Taglib Spring Security

Sometimes, it is better to hide some unauthorized links rather than letting them available and showing the access denied page when they are requested.

Spring Security has its own taglib which provides basic support for accessing security information and applying security constraints in JSPs. [3]

To use Spring security taglib in JSP pages, you need to add the taglib declaration to your project as shown in the source code bellow:

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<sec:authorize ifAllGranted="ROLE_USER">
  Utilisateur : <sec:authentication property="principal.username"/>
</sec:authorize>

To use Spring security Taglib in a facelets pages is a little bit more complicated.

  • We need to add XML namespaces declaration for Spring security taglib into facelet page as highlighted in this source code.
<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:rich="http://richfaces.org/rich"
    xmlns:sec="http://www.springframework.org/security/tags">
  • Create springsecurity.taglib.xml file into the WEB-INF file and a param declaration to reference this file in the web.xml file.
	<context-param>
		<param-name>facelets.LIBRARIES</param-name>
		<param-value>/WEB-INF/springsecurity.taglib.xml</param-value>
	</context-param>

This is the source code of springsecurity.taglib.xml I used in this prototype project. But this file has to be changed if you are using JSF 2.0. For more detail, read the spring documentation in this link.

<?xml version="1.0"?>
<!DOCTYPE facelet-taglib PUBLIC
  "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN"
  "http://java.sun.com/dtd/facelet-taglib_1_0.dtd">
<facelet-taglib>
	<namespace>http://www.springframework.org/security/tags</namespace>
	<tag>
		<tag-name>authorize</tag-name>
		<handler-class>org.springframework.faces.security.Jsf12FaceletsAuthorizeTagHandler</handler-class>
	</tag>
	<function>
		<function-name>areAllGranted</function-name>
		<function-class>org.springframework.faces.security.Jsf12FaceletsAuthorizeTagUtils</function-class>
		<function-signature>boolean areAllGranted(java.lang.String)</function-signature>
	</function>
	<function>
		<function-name>areAnyGranted</function-name>
		<function-class>org.springframework.faces.security.Jsf12FaceletsAuthorizeTagUtils</function-class>
		<function-signature>boolean areAnyGranted(java.lang.String)</function-signature>
	</function>
	<function>
		<function-name>areNotGranted</function-name>
		<function-class>org.springframework.faces.security.Jsf12FaceletsAuthorizeTagUtils</function-class>
		<function-signature>boolean areNotGranted(java.lang.String)</function-signature>
	</function>
	<function>
		<function-name>isAllowed</function-name>
		<function-class>org.springframework.faces.security.Jsf12FaceletsAuthorizeTagUtils</function-class>
		<function-signature>boolean isAllowed(java.lang.String, java.lang.String)</function-signature>
	</function>
</facelet-taglib>

  • Add this dependency to the pom.xml file
		<dependency>
			<groupId>org.springframework.webflow</groupId>
			<artifactId>spring-faces</artifactId>
			<version>2.2.1.RELEASE</version>
		</dependency>

Usually, the admin menu panel is visible only for users having the admin role. To implement this behavior, the panel source code is nested into the spring security authorize tag.

<sec:authorize access="hasAnyRole('ROLE_ADMIN')" >
	<rich:panelMenuGroup label="Admin">
		<rich:panelMenuItem >
				 <h:outputLink value="../admin/admin.jsf" >Users</h:outputLink>
		</rich:panelMenuItem> 
	</rich:panelMenuGroup>
</sec:authorize>

-Method authorization

Spring security allows method execution authorization management. It provides annotations which can contain expression attributes which are applied before and after the method invocation. To enable support for them, the attribute global-method-security has to be assigned the value enabled:

<global-method-security pre-post-annotations="enabled"/>

The source code above is added to application-context-security.xml file.

In this example we made a choice to allow only users having ROLE_CUSTOMER role to add customers.

import com.mycompany.dao.ICustomerDao;
import com.mycompany.entity.Customer;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.security.access.prepost.PreAuthorize;

public class CustomerDao extends HibernateDaoSupport implements ICustomerDao{

    @PreAuthorize("hasRole('ROLE_CUSTOMER')")
    public void save(Customer customer) {
        getHibernateTemplate().save(customer);
    }

// Other methods ....

}

To test Spring method execution authorization, we created a user “orderManager” which doesn’t have the role ROLE_CUSTOMER. When this user tries to save a customer, the application display the caught error message “Access is denied”.

Application example (Access is denied message)


Spring Security is a powerful framework to secure JEE applications. It has many other features to manage authentication and access-control services for java/JEE applications. I had used Spring Security since the project had a name Acegi. I think that the framewok has made a lot of progress and I recommend it for Securing web applications.

Reference:
[1] en.wikipedia.org
[2] searchsecurity.techtarget.com
[3] www.springsource.org

Advertisements

Using JSF RichFaces with Spring and JPA

JSF (Java Server Faces) is the most serious successor to the famous Struts Framework. It has a large success and it is adopted in most of the recent JEE projects. JSF is a standard and it has very strong community and industry support.

JSF is a MVC (Model-View-Controller) web framework based on component driven UI design model. It allows developers to concentrate on application business logic rather than on little details of HTML.

   

Photo credit: st_dimov

Many libraries come to extend JSF framework with Ajax components to help creating rich user interfaces. The most used libraries are :

    RichFaces ( JBoss project)
    ICEfaces (ICEsoft project)
    MyFaces (Apache project)

In this article, I present a project example to explain, in first step, how to integrate JSF with Spring and JPA and, in second step, how to use RichFaces to enhance the application interface.

1 – Create a basic JSF project

You can browse the source code of the project example in this link or you can checkout the project source code from Google SVN repository in this URL https://project4example2.googlecode.com
/svn/trunk
. After you check out the project into your IDE, the project will be structured as shown in the picture.

1.1 – Add JSF dependencies

To add JSF support to the application, you need to add some dependencies to the pom.xml file as shown in the source code bellow.

	....
	<dependencies>
		.......
		<dependency>
			<groupId>javax.faces</groupId>
			<artifactId>jsf-impl</artifactId>
			<version>1.2_08</version>
		</dependency>

		<dependency>
			<groupId>javax.faces</groupId>
			<artifactId>jsf-api</artifactId>
			<version>1.2_08</version>
		</dependency>

		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
			<version>1.1.2</version>
			<scope>compile</scope>
		</dependency>
		
		<dependency>
			<groupId>com.sun.facelets</groupId>
			<artifactId>jsf-facelets</artifactId>
			<version>1.1.14</version>
		</dependency>

		<dependency>
			<groupId>javax.el</groupId>
			<artifactId>el-api</artifactId>
			<version>1.0</version>
			<scope>provided</scope>
		</dependency>

		<dependency>
			<groupId>el-impl</groupId>
			<artifactId>el-impl</artifactId>
			<version>1.0</version>
			<scope>provided</scope>
		</dependency>
		......
	<dependencies>
   

1.2 – Add JSF configuration to web.xml file

FacesServlet must be configured in web.xml, it is the central controller for the JSF application. It receives all requests for the JSF application and initializes the JSF components before the JSP or XHTML is displayed.

	......
	<context-param>
		<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
		<param-value>.xhtml</param-value>
	</context-param>

	<servlet>
		<servlet-name>Faces Servlet</servlet-name>
		<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>Faces Servlet</servlet-name>
		<url-pattern>*.jsf</url-pattern>
	</servlet-mapping>
	......

1.3 – Create faces-config.xml file

faces-config.xml allows to configure the application, managed beans, convertors, validators, and navigation rules.

<?xml version="1.0" encoding="UTF-8"?>
<faces-config version="1.2" xmlns="http://java.sun.com/xml/ns/javaee"
	xmlns:xi="http://www.w3.org/2001/XInclude" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
http://java.sun.com/xml/ns/javaee/web-facesconfig_1_2.xsd">
	
	<managed-bean>
		<description>customer</description>
		<managed-bean-name>customer</managed-bean-name>
		<managed-bean-class>
			com.mycompany.bean.CustomerController
		</managed-bean-class>
		<managed-bean-scope>request</managed-bean-scope>
		<managed-property>
			<property-name>customerDao</property-name>
			<value>#{customerDao}</value>
		</managed-property>
	</managed-bean>
	
	<application>
		<locale-config>
            <default-locale>en</default-locale>
        </locale-config>
		
		<message-bundle>messages</message-bundle>
		
		<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
	</application>
</faces-config>

In the faces-config.xml, we specify SpringBeanFacesELResolver as el-resolver (Expression Language Resolver). The #{customerDao} el-expression (line 18) will be resolved by Spring framework, costomerDao is defined in Spring application-context.xml file.

1.4 -Create managed bean

JSF application uses a bean with each page in the application. The bean defines the properties and methods associated with the UI components used on the page. A bean can also define a set of methods that perform functions, such as validating the component’s data, for the component. The model object bean is like any other JavaBeans component: it has a set of accessor methods. The source code below present a managed bean used in this application example to add a customer.

import java.util.List;
import com.mycompany.dao.ICustomerDao;
import com.mycompany.entity.Customer;
import com.mycompany.entity.CustomerOrder;

/**
 * @author abdelkafi samer
 */
public class CustomerController {
private ICustomerDao customerDao;
private String customerId;
private String taxId;
private String name;
private String adresse;
.............
.....
private List<CustomerOrder> customerOrders;
private List<Customer> customers;
    
public void save(){
    	Customer customer= new Customer(Integer.parseInt(taxId), name, adresse, city, state, zip, phone, null);
    	customerDao.save(customer);
}

public ICustomerDao getCustomerDao() {
	return customerDao;
}


// getters and setters
................
.......
}

1.5 – Create facelets files

Using facelets template increase re-use and simplify maintenance on your JavaServer Faces project. The picture bellow prent the template used in this application example. To browse the source code click on the file name of the page.

template.xhtml

header.xhtml
menu.xhtml
customerEdit.xhtml

The picture below presents the basic JSF screen of the application.

2 – Add RichFaces Support to the application

In this part, I present a way to enhance JSF application user interface by using RichFaces library.

2.1 – Add richfaces dependencies

In the pom.xml file we need to add RichFaces dependencies as shown in the source code bellow.

<dependencies>
	...........
	<dependency>
		<groupId>org.richfaces.ui</groupId>
		<artifactId>richfaces-ui</artifactId>
		<version>3.3.3.Final</version>
	</dependency>

	<dependency>
		<groupId>org.richfaces.framework</groupId>
		<artifactId>richfaces-api</artifactId>
		<version>3.3.3.Final</version>
	</dependency>

	<dependency>
		<groupId>org.richfaces.framework</groupId>
		<artifactId>richfaces-impl</artifactId>
		<version>3.3.3.Final</version>
	</dependency>
		<dependency>
		<groupId>com.uwyn</groupId>
		<artifactId>jhighlight</artifactId>
		<version>1.0</version>
	</dependency>
	..........
</dependencies>

2.2 – Add reachfaces pram and filter to web.xml file

RichFaces need some parameters (SKIN, VIEW_HANDLERS, LoadScriptStrategy …) to be specified in web.xml file.


	<context-param>
		<param-name>org.richfaces.SKIN</param-name>
		<param-value>blueSky</param-value>
	</context-param>
	
	<context-param>
		<param-name>org.ajax4jsf.VIEW_HANDLERS</param-name>
		<param-value>com.sun.facelets.FaceletViewHandler</param-value>
	</context-param>

	<context-param>
		<param-name>org.richfaces.LoadScriptStrategy</param-name>
		<param-value>ALL</param-value>
	</context-param>
	
	<context-param>
	    <param-name>org.richfaces.LoadStyleStrategy</param-name>
	    <param-value>ALL</param-value>
	</context-param>
	
	<filter>
		<display-name>RichFaces Filter</display-name>
		<filter-name>richfaces</filter-name>
		<filter-class>org.ajax4jsf.Filter</filter-class>
	</filter>
	<filter-mapping>
		<filter-name>richfaces</filter-name>
		<servlet-name>Faces Servlet</servlet-name>
		<dispatcher>REQUEST</dispatcher>
		<dispatcher>FORWARD</dispatcher>
		<dispatcher>INCLUDE</dispatcher>
	</filter-mapping>


2.3 – Modify Facelets files

RichFaces has many components, you can explore them from this link.

To use Richfaces component we need to add xmlns (xml namespaces) to the facelets file and replace basic JSF tag by rich faces one.

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:a4j="http://richfaces.org/a4j"
	xmlns:rich="http://richfaces.org/rich">

<ui:composition template="./template/template.xhtml">
  
<ui:define name="body">
 
<f:view >

	<a4j:form>
		<rich:panel>
        <f:facet name="header">
        	<h:outputText value="Edit Customer"/>
        </f:facet>
        <h:panelGrid columns="3" title="Customer" rowClasses="s1row" columnClasses="wfcol1,wfcol2,wfcol3">
        <h:outputText value="Name: " />
			<h:inputText value="#{customer.name}" id="name" required="true"/>
			<rich:message for="name" />
			
			<h:outputText value="Phone: " />
			<h:inputText value="#{customer.phone}" id="phone" required="true"/>
			<rich:message for="phone" />
			
			<h:outputText value="Address: " />
			<h:inputText value="#{customer.adresse}" id="adresse" required="true"/>
			<rich:message for="adresse" />
			
			<h:outputText value="TaxId: " />
			<h:inputText value="#{customer.taxId}" id="taxId" required="true">
				<f:validateLongRange minimum="0" maximum="100"/>
			</h:inputText>
			<rich:message for="taxId" />
			
			<h:outputText value="City: " />
			<h:inputText value="#{customer.city}" id="city" required="true"/>
			<rich:message for="city" />
			
			<h:outputText value="State: " />
			<h:inputText value="#{customer.state}" id="state" required="true"/>
			<rich:message for="state" />
			
			<h:outputText value="Zip: " />
			<h:inputText value="#{customer.zip}" id="zip" required="true">
				<f:validateLongRange minimum="0" maximum="9999"/>
			</h:inputText>
			<rich:message for="zip" />
			
			<f:facet name="footer"> 
				<a4j:commandButton action="#{customer.save}"  value="save"/>
			</f:facet>
			</h:panelGrid>
    	</rich:panel>
				
	</a4j:form>
	
</f:view>

</ui:define>	
</ui:composition>

</html>

This picture presents an application screen after Richfaces integration. This screen uses Ajax to communicate with the server. The save button doesn’t reload the whole page, it just call the save method in the managed bean and update the screen.