Spring MVC Security Login and Logout Example

By Arvind Rai, June 25, 2019
This page will walk through Spring MVC Security custom login form and logout example with CSRF protection using annotation and XML configuration. Spring Security provides a login form by default and if we want to use our custom login form, we can achieve it by using spring security annotation as well as XML configuration. Spring security provides default URLs for login and logout which can be changed as required using JavaConfig as well as XML configuration. In spring 4 security, CSRF protection is enabled by default in XML configuration as in JavaConfig. We can disable and enable CSRF protection as required. If we are using CSRF protection, the logout request must be POST. Here we will create a spring security application that will provide an UI to get student detail by entering the student id. We will use in-memory authentication creating a user with a user name, password and role. Here we will provide complete example with annotation and XML configuration step by step.

Software Used

Find the software used in our demo.
1. Java 8
2. Spring 4.2.5.RELEASE
3. Tomcat 8
4. Gradle
5. Eclipse

Gradle File to Build Project

Find the gradle file to build the project and resolve the JAR dependencies.
build.gradle
apply plugin: 'java'
apply plugin: 'eclipse'
apply plugin: 'war'
archivesBaseName = 'spring4javaconfig'
version = '1' 
repositories {
    mavenCentral()
}
dependencies {
    compile 'org.springframework.boot:spring-boot-starter-web:1.3.3.RELEASE'
    compile 'org.springframework.boot:spring-boot-starter-security:1.3.3.RELEASE'
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat:1.3.3.RELEASE'    
} 

Spring 4 Security and CSRF

CSRF is Cross Site Request Forgery. Spring security protects our application from CSRF. In JavaConfig, CSRF protection is enabled by default. Now Spring security version 4 onwards XML configuration is also CSRF protection enabled by default. We can disable CSRF protection if required. Find the below points regarding CSRF protection to use in our spring security application.
1. To use CSRF protection in our views, include a hidden HTML field within <form>.
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>	
 
2. In case we are using spring <form:form>, we need not to include tag for CSRF.
3. Find the XML configuration to disable CSRF protection.
<http>
	<!-- Other Configurations -->
	<csrf disabled="true"/>
</http> 
4. Find the JavaConfig to disable CSRF protection.
protected void configure(HttpSecurity http) throws Exception {
	http.csrf().disable();
} 
5. If CSRF protection is enabled, logout request must be POST.

Spring 4 MVC Security Custom Login Form and Logout Example using Annotation

Here we will create a spring 4 MVC security custom login form and logout example using annotation. The configurations related to custom login form and logout are done in JavaConfig. We will create two configuration file, one for spring security configuration and another for spring MVC configuration. We will create a service class that will provide student detail and will create views for the same which will be secured and can be accessed only after authentication. We will use in-memory user authentication. We will handle CSRF protection in our form by including a hidden field for CSRF parameter. Spring security enables CSRF protection in JavaConfig by default.

Project Structure in Eclipse for JavaConfig

Find the print screen of project structure in eclipse with JavaConfig.
Spring 4 MVC Security Custom Login Form and Logout Example with CSRF protection using Annotation and XML Configuration

Create JavaConfig for Spring Security

Find the JavaConfig used in our spring security custom login and logout application.
SecurityConfig.java
package com.concretepage.config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests().
		antMatchers("/secure/**").access("hasRole('ROLE_ADMIN')").
		and().formLogin().  //login configuration
                loginPage("/customLogin.jsp").
                loginProcessingUrl("/appLogin").
                usernameParameter("app_username").
                passwordParameter("app_password").
                defaultSuccessUrl("/secure/home").	
		and().logout().    //logout configuration
		logoutUrl("/appLogout"). 
		logoutSuccessUrl("/customLogin.jsp");
	} 
	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
		auth.inMemoryAuthentication().withUser("ram").password("ram123").roles("ADMIN");
	}	
} 

authorizeRequests(): It allows restricted access. HTTP requests are authorized before being served.
antMatchers(): It matches the URL with given pattern.
access(): It checks if the USER has provided role.
formLogin(): Enables form based authentication.
loginPage(): It specifies the custom login page URL.
loginProcessingUrl(): It specifies the URL using which username and password is validated.
usernameParameter(): It specifies the field name to enter user name which is used by spring security to validate. If not specified then default is username.
passwordParameter(): It specifies the field name to enter password which is used by spring security to validate. If not specified then default is password.
defaultSuccessUrl(): It specifies the default URL which is used by spring security after successful authentication.
logout(): It support the logout functionality in spring security application.
logoutUrl(): If defines the URL for logout. If CSRF protection is enabled, logout request must be POST.
logoutSuccessUrl(): It specifies the URL which is used by spring security after successful logout.

configureGlobal(): It configures AuthenticationManager. Here we are using in-memory authentication in our example.

Create JavaConfig for Spring MVC

Find the JavaConfig for spring MVC.
AppConfig.java
package com.concretepage.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.view.InternalResourceViewResolver;
@Configuration
@ComponentScan("com.concretepage")
@Import(SecurityConfig.class)
@EnableWebMvc
public class AppConfig {
    @Bean  
    public InternalResourceViewResolver viewResolver() {  
	InternalResourceViewResolver resolver = new InternalResourceViewResolver();  
        resolver.setPrefix("/WEB-INF/secure/");  
        resolver.setSuffix(".jsp");
        return resolver;  
    }	
} 

@EnableWebMvc: This annotation imports web MVC configuration from WebMvcConfigurationSupport.
InternalResourceViewResolver: Using prefix and suffix, URL is created to access internal resource.

Create Custom Login Form

We need to create a form which action will be defined by http.loginProcessingUrl() and user name and password field name will be defined as specified by htt.usernameParameter() and http.passwordParameter() respectively. As CSRF protection is enabled, we need to include a hidden field for CSRF. We need to submit the form using POST method.
customLogin.jsp
<html>
    <head>
        <title>Spring 4 Security Example</title>
    </head>
    <body>
       <h3>Spring 4 Security Example</h3>
        <font color="red">
		   ${SPRING_SECURITY_LAST_EXCEPTION.message}
        </font>
	<form action="<%=request.getContextPath()%>/appLogin" method="POST">
		Enter UserName:	<input type="text" name="app_username"/><br/><br/>
		Enter Password: <input type="password" name="app_password"/> <br/><br/>			
		<input type="submit" value="Login"/>
		<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>			
	</form>
    <body>
</html>   


Create Logout form in Secure Views

In our case CSRF protection is enabled which is default behavior of spring 4 security. Hence logout request must be submitted as POST. We have created a HTML form whose action is defined with the value specified by http.logoutUrl() in security configuration. We will include a hidden tag for CSRF within our HTML form.
home.jsp
<html>
    <head>
        <title>Spring 4 Security Example</title>
    </head>
    <body>
      Welcome! To get student detail <a href="<%=request.getContextPath()%>/secure/studentDetail">click here.</a>
      <form action="<%=request.getContextPath()%>/appLogout" method="POST">
        <input type="submit" value="Logout"/>
        <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>		
      </form>      
    </body>
</html> 
student.jsp
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
<html>
<head><title>Spring 4 Security Example</title></head>
<body>
  <h3>Spring 4 Security Example </h3>
  <form:form action="result" method="POST" commandName="student">
    <form:input  path="stdId"/> <br/>
    <input type="submit" value="Submit">
  </form:form>
</body>
</html>    
We need to observe here in student.jsp that in case we are using spring <form:form> tag, we need not to include hidden HTML field for CSRF parameter.
output.jsp
<html>
    <head>
        <title>Spring 4 Security Example</title>
    </head>
    <body>
          <h3>Spring 4 Security Example</h3>
          Student Name:  ${stdName}
	  <form action="<%=request.getContextPath()%>/appLogout" method="POST">
	     <input type="submit" value="Logout"/>
	     <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>		
	  </form>
    </body>
</html>  

Create Spring Web Application Initializer

To register DelegatingFilterProxy using Servlet 3 without web.xml, we need to create a class which will implement AbstractSecurityWebApplicationInitializer.
SecurityInitializer.java
package com.concretepage.config;
import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SecurityInitializer extends AbstractSecurityWebApplicationInitializer {
} 
To register DispatcherServlet we will create a class which will implement AbstractAnnotationConfigDispatcherServletInitializer.
WebAppInitializer.java
package com.concretepage.config;
import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;
public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
	@Override
	protected Class<?>[] getRootConfigClasses() {
		return new Class[] { AppConfig.class };
	}
	@Override
	protected Class<?>[] getServletConfigClasses() {
		return null;
	}
	@Override
	protected String[] getServletMappings() {
		return new String[] { "/" };
	}
} 

Create Service and Controller Class

We are creating a service that will provide student detail by student id and will be assed in controller.
StudentService.java
package com.concretepage.service;
import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Service;
import com.concretepage.bean.Student;
@Service
public class StudentService {
	Map<Integer, Student> map = new HashMap<>();
	{
		map.put(1, new Student(1, "Ram"));
		map.put(2, new Student(2, "Shyam"));
		map.put(3, new Student(3, "Rahim"));
	}
	public String getStudentName(int id) {
		System.out.println("Fetching student for the id:"+ id);
		Student std = map.get(id);
		return std.getStdName();
	}
} 
StudentController.java
package com.concretepage.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import com.concretepage.bean.Student;
import com.concretepage.service.StudentService;
@Controller
@RequestMapping("/secure")
public class StudentController {
	@Autowired
        private StudentService service;
	@RequestMapping(value="/home")
	public String homePage() {
 		return "home";
 	}    
	@RequestMapping(value="/studentDetail")
	public String studentDetail(Model model) {
		model.addAttribute("student", new Student());
 		return "student";
 	}
	@RequestMapping(value="/result", method=RequestMethod.POST)
	public String success(@ModelAttribute("student") Student student, ModelMap model) {
		String stdName = service.getStudentName(student.getStdId());
		model.addAttribute("stdName", stdName);
		return "output";
	}
} 
Student.java
package com.concretepage.bean;
public class Student {
	private int stdId;
	private String stdName;
	public Student(){}
	public Student(int stdId, String stdName) {
		this.stdId = stdId;
		this.stdName = stdName;
	}
	public int getStdId() {
		return stdId;
	}
	public void setStdId(int stdId) {
		this.stdId = stdId;
	}
	public String getStdName() {
		return stdName;
	}
	public void setStdName(String stdName) {
		this.stdName = stdName;
	}
} 

Spring 4 MVC Security Custom Login Form and Logout Example using XML Configuration

Here we will create spring 4 MVC security custom login form and logout example using XML configuration. We will create a spring context XML file equivalent to spring security JavaConfig. The controller, service and views with custom login and logout page will be same as used in our spring security application using annotation. Spring security version 4 onwards, CSRF protection is enabled by default in XML configuration as in JavaConfig. We will use in-memory user authentication.

Project Structure in Eclipse for XML Configuration

Find the print screen of our project structure in eclipse with XML configuration.
Spring 4 MVC Security Custom Login Form and Logout Example with CSRF protection using Annotation and XML Configuration

Create XML Configuration for Spring Security

We are creating a spring context xml file for spring security which is equivalent to SecurityConfig class created in spring security project using JavaConfig.
security-config.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
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/security
	http://www.springframework.org/schema/security/spring-security.xsd">
	<http auto-config="true">
		<intercept-url  pattern="/secure/**" access="hasRole('ROLE_ADMIN')" />
		<form-login 
		   login-page="/customLogin.jsp" 
		   login-processing-url="/appLogin"
		   username-parameter="app_username"
		   password-parameter="app_password"
		   default-target-url="/secure/home"/>
		<logout 
		   logout-url="/appLogout" 
		   logout-success-url="/customLogin.jsp"/>  
	</http>
	<authentication-manager>
		<authentication-provider>
			<user-service>
				<user name="ram" password="ram123" authorities="ROLE_ADMIN" />
			</user-service>
		</authentication-provider>
	</authentication-manager>
</beans:beans> 

<http>: It contains elements of HTTP security configuration.
auto-config: If the value is true, it registers basic spring security configuration.

<intercept-url> : It defines URL pattern accessible for specified role using pattern and access attribute.
pattern: Defines URL pattern.
access : Defines roles accessible for the given URL pattern.

<form-login>: Configures form login.
login-page : Defines custom login page URL.
login-processing-url : Defines URL used for authentication using username and password.
username-parameter: Defines field name for username.
password-parameter : Defines field name for password.
default-target-url : Defines default target URL used by spring security after successful login.

<logout>: Defines logout configuration.
logout-url: Defines logout URL used by spring security for logout.
logout-success-url: Defines URL used by spring security after successful logout.

<authentication-manager> : It registers AuthenticationManager.
<authentication-provider> : Authentication provider that defines user service for authentication.
<user-service> : It creates in-memory UserDetailsService.
<user> : It creates a user with user name, password and roles.

Create Spring Context XML

In spring context XML, we using component-scan which will auto detect the service class used in our example. To access internal resource , we have configured InternalResourceViewResolver which will specify prefix and suffix for the URL redirected by spring MVC controller.
dispatcher-servlet.xml
<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.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd">
	<context:component-scan base-package="com.concretepage" />
	<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	  <property name="prefix" value="/WEB-INF/secure/"/>
	  <property name="suffix" value=".jsp"/> 
        </bean>
</beans> 

web.xml with Spring Security Configuration

Find web.xml used in our spring security application with XML configuration.
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"
    xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
    http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">

	<display-name>Spring 4 Security Example</display-name>
	<servlet>
		<servlet-name>dispatcher</servlet-name>
		<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>
	<servlet-mapping>
		<servlet-name>dispatcher</servlet-name>
		<url-pattern>/</url-pattern>
	</servlet-mapping>
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
		   /WEB-INF/dispatcher-servlet.xml,
		   /WEB-INF/security-config.xml
		</param-value>
	</context-param>
	<listener>
		<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<!-- Spring Security Configuration -->
	<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>
</web-app> 

DispatcherServlet: It handles HTTP request in spring MVC.
ContextLoaderListener : It listens to start and stop spring WebApplicationContext
DelegatingFilterProxy : This is a proxy for Servlet filter to delegate to spring managed bean.

Run Application

To run our spring security application, use the below URLs.
1. To run spring security application using annotation, find the URL.
http://localhost:8080/spring4javaconfig-1/customLogin.jsp

2. To run the spring security application using XML configuration, find the URL.
http://localhost:8080/spring4xml-1/customLogin.jsp

Find the screen shots of the output. Enter username/password as ram/ram123
Spring 4 MVC Security Custom Login Form and Logout Example with CSRF protection using Annotation and XML Configuration
Click to get student detail.
Spring 4 MVC Security Custom Login Form and Logout Example with CSRF protection using Annotation and XML Configuration
Enter student id.
Spring 4 MVC Security Custom Login Form and Logout Example with CSRF protection using Annotation and XML Configuration
Student name is displayed.
Spring 4 MVC Security Custom Login Form and Logout Example with CSRF protection using Annotation and XML Configuration
When we logout, we will go to login page.

Now I am done. Happy spring security learning!

Download Complete Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us