In this article, you will learn how to secure applications using the Spring Security framework. In particular how to secure URL, authenticate and authorize users against a database.

web.xml

In the web deployment descriptor, you register ContextLoaderListener to load the root application context at startup and Spring MVC’s DispatcherServlet to dispatch requests.

<?xml version="1.0" encoding="UTF-8"?>
<web-app 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 http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
	version="2.5">

	<display-name>MyDashboard</display-name>
	
	<welcome-file-list>
		<welcome-file>login.jsp</welcome-file>
	</welcome-file-list>

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			classpath:board-security.xml
		</param-value>
	</context-param>

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

	<servlet>
		<servlet-name>board</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
	</servlet>
	<servlet-mapping>
		<servlet-name>board</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
</web-app>

Note that you have mapped the URL pattern / to DispatcherServlet, meaning everything under the application’s root directory will be handled by this servlet.

In the web layer configuration file (i.e., board-servlet.xml), you define a view resolver to resolve view names into JSP files located in the /WEB-INF/jsp/ directory.
Below the configuration file for “board” servlet declared in the web.xml, named “board-servlet.xml”:

<beans xmlns="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
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd">

	<context:component-scan base-package="org.madbit.springsecurity.web" />
	
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix" value="/WEB-INF/jsp/" />
		<property name="suffix" value=".jsp" />
	</bean>
</beans>

Controller

Now you create the controller, also used for authentication purposes.

@Controller
public class LoginController {
	@RequestMapping(value="/welcome", method = RequestMethod.GET)
	public String printWelcome(ModelMap model, Principal principal ) {
		return "welcome"; 
	}
 
	@RequestMapping(value="/login", method = RequestMethod.GET)
	public String login(ModelMap model) { 
		return "login"; 
	}
	
	@RequestMapping(value="/loginfailed", method = RequestMethod.GET)
	public String loginerror(ModelMap model) { 
		model.addAttribute("error", "true");
		return "login"; 
	}
	
	@RequestMapping(value="/logout", method = RequestMethod.GET)
	public String logout(ModelMap model) { 
		return "login"; 
	}
}

Below an example of welcome.jsp page.

<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="security" uri="http://www.springframework.org/security/tags" %>

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body>
	<h2>Welcome! <security:authentication property="name" /></h2>
	
	Your roles:
	<security:authentication property="authorities" var="authorities" />
	<ul>
	<c:forEach items="${authorities}" var="authority">
		<li>${authority.authority}</li>
	</c:forEach>
	</ul>
	<a href="<c:url value="/j_spring_security_logout" />" > Logout</a>
</body>
</html>

Securing URL Access

Now, let’s secure this web application’s URL access with Spring Security. First, you have to configure a DelegatingFilterProxy instance in web.xml to delegate HTTP request filtering to a filter defined in Spring Security.

To do this, add the following lines to the 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> 
</filter-mapping>

The responsibility of DelegatingFilterProxyis simply to delegate HTTP request filtering to a Spring bean that implements the java.util.logging.Filterinterface.
By default, it delegates to a bean whose name is the same as its property, but you can override the bean name in its targetBeanName init parameter.
As Spring Security will automatically configure a filter chain with the name springSecurityFilterChain when you enable web application security, you can simply use this name for your DelegatingFilterProxy instance.

Now, what we want it’s make secure the URL “/welcome“.
You create a Spring security configurations file (e.g board-security.xml) with the following content:

<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.1.xsd
        http://www.springframework.org/schema/security
        http://www.springframework.org/schema/security/spring-security-3.0.xsd">

    <http auto-config="true">
    	<intercept-url pattern="/welcome" access="ROLE_USER" />
        <anonymous username="guest" granted-authority="ROLE_GUEST"/>
        <form-login login-page="/login" default-target-url="/welcome" authentication-failure-url="/loginfailed" /> 
        <logout logout-success-url="/logout"/>
        <remember-me />
   	</http>

	<authentication-manager>
		<authentication-provider>
			<jdbc-user-service data-source-ref="dataSource" />
			<password-encoder hash="sha" />
		</authentication-provider>
	</authentication-manager>
</beans:beans>

The element automatically configures the basic security services that a typical web application needs. Inside the configuration element, you can restrict access to particular URLs with one or more elements. Each element specifies a URL pattern and a set of access attributes required to access the URLs. Remember that you may need include a wildcard (*) at the end of a URL pattern if the URL has request parameters.

Now welcome path it’s accessible only to authenticated users and that belong to group ROLE_USER.

In this example we assumed that the user’s password on your DB are encrypted with SHA-1 hash alghoritm. Spring security supports many other has algorithms.

An example of bean “dataSource” bean definition, used by authentication-provider, is the following:

<beans xmlns="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.1.xsd">
	
	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="com.mysql.jdbc.Driver" />
		<property name="url" value="jdbc:mysql://localhost:3306/mytest" />
		<property name="username" value="root" />
		<property name="password" value="root" />
	</bean>
</beans>

By default Spring authenticates users on a datamodel defined as below:

CREATE TABLE USERS ( 
        USERNAME VARCHAR(10) NOT NULL, 
        PASSWORD VARCHAR(32) NOT NULL, 
        ENABLED SMALLINT, 
        PRIMARY KEY (USERNAME) 
);

CREATE TABLE AUTHORITIES ( 
        USERNAME VARCHAR(10) NOT NULL, 
        AUTHORITY VARCHAR(10) NOT NULL, 
        FOREIGN KEY (USERNAME) REFERENCES USERS(USERNAME)
);

Of course, you can define your own datamodel and authenticate users on it just changing the jdbc-user-service definition in board-security.xml file and specifying the appropriate SQL query.
Below an example:

<jdbc-user-service data-source-ref="dataSource" 
    users-by-username-query="SELECT username, password, 'true' as enabled FROM member WHERE username = ?" 
    authorities-by-username-query="SELECT member.username, member_role.role as authorities FROM member, member_role WHERE member.username = ? AND member.id = member_role.member_id" />

Logging In to Web Applications

The last step is create a login page. The form-based login service will render a web page that contains a login form for users to input their login details and process the login form submission. It’s configured via the element.
By default, Spring Security automatically creates a login page and maps it to the URL /spring_security_login.
If you don’t prefer the default login page, you can provide a custom login page of your own. For example, you can create the following login.jsp.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<html>
<head>
<title>Login</title>
<style>
.errorblock {
	color: #ff0000;
	background-color: #ffEEEE;
	border: 3px solid #ff0000;
	padding: 8px;
	margin: 16px;
}
</style>
</head>

<body onload='document.login_form.j_username.focus();'>
	<c:if test="${not empty error}">
		<div class="errorblock">
			Your login attempt was not successful, try again.<br /> Caused :
			${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message}
		</div>
	</c:if>
	
	<form name="login_form" method="POST" action="<c:url value="j_spring_security_check" />">
		<table>
			<tr>
				<td align="right">Username</td>
				<td><input type="text" name="j_username" />
				</td>
			</tr>
			<tr>
				<td align="right">Password</td>
				<td><input type="password" name="j_password" />
				</td>
			</tr>
			<tr>
				<td align="right">Remember me</td>
				<td><input type="checkbox" name="_spring_security_remember_me" />
				</td>
			</tr>
			<tr>
				<td colspan="2" align="right"><input type="submit"
					value="Login" /> <input type="reset" value="Reset" /></td>
			</tr>
		</table>
	</form>
</body>
</html>

Source code