Spring Security: Default form-based login provided by Spring framework

In this article, we will implement an example to demonstrate how we could integrate Spring Security in a Spring MVC application. Spring Security intercepts all incoming http requests applying servlet filters and route them according to security configuration. This way we can secure the URL access only to authenticated users

In this example,

  • /admin* will be intercepted by the security filters and we need to KEY-IN the correct credentials (Username/Password) to access
  • Other like /home* won’t be intercepted by security filters

Technology Used

  • Java 1.7
  • Eclipse Luna IDE
  • Spring-4.0.0-RELEASE
  • Apache-Maven-3.2.1
  • Apache Tomcat 7.0.54

Mavenize or download required jars

Add Spring-4.0.0 and Spring-security-3.2.0 dependencies to the pom.xml

<dependencies>
		<!-- junit -->
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>

		<!-- jstl for jsp page -->
		<dependency>
			<groupId>jstl</groupId>
			<artifactId>jstl</artifactId>
			<version>${jstl.version}</version>
		</dependency>

		<!-- servlet -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>javax.servlet-api</artifactId>
			<version>3.1.0</version>
			<scope>provided</scope>
		</dependency>

		<!-- Spring 4.0.0.RELEASE Framework -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<!-- Spring Security 3.2.0.RELEASE Framework -->
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-core</artifactId>
			<version>${spring.security.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-web</artifactId>
			<version>${spring.security.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-config</artifactId>
			<version>${spring.security.version}</version>
		</dependency>
	</dependencies>

Folks who aren’t familiar with Maven concepts or don’t require maven for their project, can download the below jars individually from the spring site and include them in the classpath

  • spring-core-4.0.0-RELEASE
  • spring-context-4.0.0-RELEASE
  • spring-beans-4.0.0-RELEASE
  • spring-aop-4.0.0-RELEASE
  • spring-expression-4.0.0-RELEASE
  • spring-web-4.0.0-RELEASE
  • spring-webmvc-4.0.0-RELEASE
  • spring-security-core-3.2.0-RELEASE
  • spring-security-web-3.2.0-RELEASE
  • spring-security-config-3.2.0-RELEASE
  • commons-logging-1.1.1
  • aopalliance-1.0
  • junit-3.8.1
  • jstl-1.2

Directory Structure

Before moving on, let us understand the directory/package structure once you create project in Eclipse IDE
Maven has to follow certain directory structure

  • src/test/java –> test related files, mostly JUnit test cases
  • src/main/java –> create java source files under this folder
  • src/main/resources –> all configuration files placed here
  • Maven Dependencies or Referenced Libraries –> includes jars in the classpath
  • WEB-INF under webapp –> stores web.xml & other configuration files related to web application

Project Structure (Package Explorer view in Eclipse)

1_SpringSecurity_Basic_Project_Structure_In_Eclipse

Jars Libraries Used in the Project (Maven Dependencies)

2_SpringSecurity_Basic_Jars_In_Classpath

Web application

For any web application, entry point is web.xml which describes how the incoming http requests are served / processed. Further, it describes about the global-context and local-context param (i.e.; <context-param> & <init-param>) for loading the files particular to project requirements & contains respective listener.

With this introduction, we will understand how we configured web.xml for our Spring Security + Spring MVC application

web.xml (the entry point –> under WEB-INF)

This web.xml file describes,

  • all http requests with wild card pattern “/” will be intercepted by the configured servlet called “DispatcherServlet” (org.springframework.web.servlet.DispatcherServlet)
  • </servlet-name> name mentioned in the web.xml is mvc-dispatcher, which on loading/exploding the war into the application server(Tomcat application server for our example) looks for the servlet filename called “mvc-dispatcher-servlet.xml”
  • <context-param> with its attributes describes the location of the file from where it has to be loaded
  • “mvc-dispatcher-servlet.xml” is the file which describes how exactly specific http requests are handled or which controllers gets invoked for certain http requests. We will see “mvc-dispatcher-servlet.xml” file for our Spring MVC + Spring Security application
  • <welcome-file-list> files under this tag is the start-up page
  • Servlet filter called “DelegatingFilterProxy” with url-pattern /* intercepts incoming http requests and enter Spring Security framework for security checks to authenticate users
  • “spring-security.xml” describes which URL needs to be intercepted along with their roles/credentials

web.xml

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

	<!-- project display for web application -->
	<display-name>SpringSecurity</display-name>

	<!-- welcome file list -->
	<welcome-file-list>
		<welcome-file>index.jsp</welcome-file>
	</welcome-file-list>

	<!-- Spring MVC DispatcherServlet: dispatches HTTP requests to registered controllers -->
	<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>/</url-pattern>
	</servlet-mapping>

	<!-- location of the root application context xml file -->
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			/WEB-INF/mvc-dispatcher-servlet.xml,
            /WEB-INF/spring-security.xml
        </param-value>
	</context-param>

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

	<!-- Spring Security -->
	<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>REQUEST</dispatcher>
		<dispatcher>FORWARD</dispatcher>
		<dispatcher>INCLUDE</dispatcher>
		<dispatcher>ERROR</dispatcher>
	</filter-mapping>
</web-app>

Dispatcher Servlet

Below mvc-dispatcher-servlet.xml file defines,

  • <context:component-scan base-package=”” /> this tag scans all classes & sub-classes under the value of base-package attribute and register them with the Spring container
  • Other bean element  for view resolver defines the logic for output rendering i.e.; viewName returned by the Controller which will be sandwiched between the prefix (WEB-INF/jsp) & suffix (.jsp)
  • Now, there should be a file under the directory as defined i.e.; (WEB-INF/jsp/<viewName>.jsp
  • Otherwise, not found exception thrown

mvc-dispatcher-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:context="http://www.springframework.org/schema/context" 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-4.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.0.xsd">

	<!-- register beans for handling incoming HTTP requests -->
	 <context:component-scan base-package="com.spring.series.security.controller" />  

	<!-- view resolver for rendering the final output -->
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<property name="prefix">
			<value>/WEB-INF/jsp/</value>
		</property>
		<property name="suffix">
			<value>.jsp</value>
		</property>
	</bean>
</beans>

Spring Security Configuration

This Spring Security configuration file describes the security URL to be intercepted and login details for that particular role

  • First element <security:http /> with pattern describes which all incoming http requests needs to be intercepted
  • Second element with <security:authentication-manager /> defines the credentials (Name/Password) for every role. For example, ROLE_ADMIN, ROLE_USER, etc.

NOTE: We can encode/hash the password or else store plain/hashed password in database. More example on this topics to follow

spring-security.xml

<beans:beans xmlns:beans="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:security="http://www.springframework.org/schema/security" 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.2.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd">

	<security:http auto-config="true">
		<security:intercept-url pattern="/admin*" access="ROLE_ADMIN" />
	</security:http>

	<security:authentication-manager>
		<security:authentication-provider>
			<security:user-service>
				<security:user name="admin" password="admin123" authorities="ROLE_ADMIN" />
			</security:user-service>
		</security:authentication-provider>
	</security:authentication-manager>
</beans:beans>

 

Let’s see coding in action

 

Controller: This is straight forward Spring Controller configuration with 2 GET request methods with their mapping attributes. Both methods returns view name along with two attributes to the view renderer to output to end user

HomeController.java

package com.spring.series.security.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

@Controller
public class HomeController {

	// http://localhost:8080/SpringSecurity/home
	@RequestMapping(value = "/home", method = RequestMethod.GET)
	public String homePage(ModelMap modelMap) {

		modelMap.addAttribute("topic", "Welcome to the Spring Security Learning");
		modelMap.addAttribute("description", "This is HOME Page");
		return "home";
	}

	// http://localhost:8080/SpringSecurity/admin
	@RequestMapping(value = "/admin", method = RequestMethod.GET)
	public ModelAndView adminPage() {

		ModelAndView modelAndView = new ModelAndView("admin");
		modelAndView.addObject("topic", "Welcome to the Spring Security Learning");
		modelAndView.addObject("description", "This is ADMIN page");
		return modelAndView;
	}
}

View Technologies (JSP Pages)

 

This is default page under webapp for direct access
index.jsp (\src\main\webapp\index.jsp)

<%@ 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">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring Security</title>
</head>
<body>
	<center>
		<b>Welcome to the Spring Security Learning</b>


<h2>This is default page</h2>


	</center>
</body>
</html>

This is home page with two messages to display and this is not protected means when we access URL ending “/home*”, Spring Security framework won’t be intercepted
home.jsp (\src\main\webapp\WEB-INF\jsp\home.jsp)

<%@ 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">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring Security</title>
</head>
<body>
	<center>
		<b>${topic}</b>


<h2>${description}</h2>


	</center>
</body>
</html>

This is admin page with protected access i.e.; only admin can access this page with correct credentials. Additionally, we got Logout link (j_spring_security_logout) to allow the logged-in user to get logged-out and disable the current session
admin.jsp (\src\main\webapp\WEB-INF\jsp\admin.jsp)

<%@ 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"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Spring Security</title>
</head>
<body>
	<center>
		<b>${topic}</b>


<h2>${description}</h2>




<h3>
			<a href="<c:url value="/j_spring_security_logout" />">Logout</a>
		</h3>


	</center>
</body>
</html>

Time to Test/Execute

 

Enter URL: http://localhost:8080/SpringSecurity/ into web browser
This is default page
3_SpringSecurity_default_url

 

 

Enter URL: http://localhost:8080/SpringSecurity/home into web browser
Directly you get to view this page, as this is not protected (Look at the security configuration in spring-security.xml file)
4_SpringSecurity_home_url

 

 

Enter URL: http://localhost:8080/SpringSecurity/admin into web browser
When you enter the above URL, then it redirects to URL http://localhost:8080/SpringSecurity/spring_security_login as this is intercepted by the security filter configured
5_SpringSecurity_admin_url_login

Wonder !!

Have you ever thought about this login page i.e.; from where this page appears?
Whenever an URL is protected then in that case Spring framework provides a default login page to user to key-in the credentials to view the page.

 

Enter Invalid Credentials
You will get below error message and URL redirected to http://localhost:8080/SpringSecurity/spring_security_login?login_error

6_SpringSecurity_admin_url_login_fail

 

 

Enter correct credentials (admin/admin123)
Admin page with an option to Logout link, clicking which will disable the current session
7_SpringSecurity_admin_url_login_success

 

Conclusion: Thus, integrating Spring Security with Spring MVC application enables certain or user-configured URLs are secured allowing access to only authenticated users.

Download project

Spring-Security-Default-form-based-login (7kB)

 

Read Also:

 

Happy Coding !!
Happy Learning !!

Spring Security: Customize Login Form