Spring Security login form integration example with Java configuration

This tutorial will show you how to integrate Spring Security into a Spring MVC application using purely Java configuration. The application won’t use a database, the user credentials are just defined as plain text in the configuration class for simplicity.

We will show you almost all of the files needed for the working application, but will only describe the parts that are strictly connected to the Spring Security integration and not just there to have a basic webapp up and running.

At the end of the tutorial you can download the whole working Maven project.

Tools used:

  • Spring Tool Suite 3.7.1.RELEASE
  • Apache Maven 3.3.9
  • Java 8
  • Tomcat 8.0.32

Looking for an XML configuration solution?

We have a similar article that uses XML configuration.

The project structure

Here is the final structure of the project:

jtuts-2016-03-01-spring-security-simple-integration-java-config-project-structure

Dependencies

Aside from Spring that we are using to build our webapp, we need two Spring Security related dependencies:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>jtuts</groupId>
    <artifactId>jtuts-spring-security-java-config</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>jtuts-spring-security-java-config</name>

    <properties>

        <!-- Dependency versions -->

        <spring.version>4.2.5.RELEASE</spring.version>
        <spring.security.version>4.0.4.RELEASE</spring.security.version>

        <servlet.api.version>3.1.0</servlet.api.version>
        <jsp.version>2.0</jsp.version>

        <!-- Plugin versions -->

        <maven.compiler.plugin.version>3.5.1</maven.compiler.plugin.version>

        <!-- Misc versions -->

        <java.version>1.8</java.version>

    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.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>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servlet.api.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>${jsp.version}</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>

    <build>
        <finalName>jtuts-spring-security-java-config</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.plugin.version}</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>
        </plugins>

    </build>

</project>

The important things to note here:

  • spring-security-web: Contains filters and related web-security infrastructure code. You’ll need it if you require Spring Security web authentication services and URL-based access-control. This also pulls in the spring-security-core dependency.
  • spring-security-config: Contains the security namespace parsing code. You need it if you are using the Spring Security XML namespace for configuration.

We also needed to set the failOnMissingWebXml property to false, because by default STS would report an error that we don’t have a web.xml.

The springSecurityFilterChain filter

One of the core elements of Spring Security is a chain of filters that determine if the user has access to a given resource. If we are using Java configuration, setting this up is really easy, we just have to create a class extending the AbstractSecurityWebApplicationInitializer class.

package com.jtuts.web.configuration.security;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;

public class SecurityWebApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
    
}

It will configure the filter in a way that is equivalent to setting it up in the web.xml like this:

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

Creating the configuration class for Spring Security

Most of the configuration goes into our SpringSecurityConfiguration class:

package com.jtuts.web.configuration.security;

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 SpringSecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.inMemoryAuthentication().withUser("admin").password("Secret123").roles("USER");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        
        http.authorizeRequests()
            .antMatchers("/login").access("permitAll")
            .antMatchers("/**").access("hasRole('ROLE_USER')")
        .and().formLogin()
            .loginPage("/login")
            .defaultSuccessUrl("/home")
            .failureUrl("/login?error=true")
        .and().logout()
            .logoutSuccessUrl("/login");
    }

}

Let’s see in detail the meaning of this code:

  • The @Configuration annotation is needed so that Spring knows that this class may be processed by the Spring container to generate bean definitions and service requests for those beans at runtime.
  • The @EnableWebSecurity annotation means that security configuration is configured in this class.
  • In the configureGlobal method we define a dummy user, that is only stored in memory for the sake of simplicity.
  • In the configure method we set the following:
    • The /login URL is accessible to anyone, but all other URLs are just for those having the USER role.
    • We use a form for login, it’s URL is /login, and if the login successful we redirect to /home and if it is unsuccessful, we redirect to /login?error=true.
    • When the user logs out successfully, we redirect them to /login.

This configuration is imported in the main application configuration:

package com.jtuts.web.configuration;

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.config.annotation.WebMvcConfigurerAdapter;

import com.jtuts.web.configuration.security.SpringSecurityConfiguration;

@EnableWebMvc
@Configuration
@Import(SpringSecurityConfiguration.class)
public class ApplicationConfiguration extends WebMvcConfigurerAdapter  {

}

The login form

The view file for the login form is login.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JTuts Spring Security integration tutorial with XML configuration</title>
</head>
<body>
    <h1>Login</h1>

    <form action="${pageContext.request.contextPath}/login" method="POST">
        <table>
            <tr>
                <td><label for="username">Username:</label></td>
                <td><input type="text" name="username"></td>
            </tr>
            <tr>
                <td><label for="password">Password:</label></td>
                <td><input type="password" name="password" /></td>
            </tr>
            <tr>
                <td><input type="submit" value="Login" /></td>
            </tr>
        </table>
        <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> 
    </form>
</body>
</html>

The important things to note here are the following:

  • The URL where we post the form (/login) is the default URL in Spring Security 4.
  • The names of the fields (username, password) are also the default names expected by Spring Security.
  • The hidden field is there because CSRF protection is enabled by default and we need a token to be able to submit the form.

Warning: In earlier versions of Spring Security the defaults mentioned could be different, so please pay attention to that if you are on an older version.

Other files

We don’t have a web XML so we use a WebApplicationInitializer to configure the application:

package com.jtuts.web.configuration;

import javax.servlet.ServletContext;
import javax.servlet.ServletRegistration;

import org.springframework.web.WebApplicationInitializer;
import org.springframework.web.context.ContextLoaderListener;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;

public class CustomWebApplicationInitializer implements WebApplicationInitializer {

    @Override
    public void onStartup(ServletContext container) {

        // Create the 'root' Spring application context
        AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
        rootContext.register(ApplicationConfiguration.class);

        // Manage the lifecycle of the root application context
        container.addListener(new ContextLoaderListener(rootContext));

        // Create the dispatcher servlet's Spring application context
        AnnotationConfigWebApplicationContext dispatcherContext = new AnnotationConfigWebApplicationContext();
        dispatcherContext.register(DispatcherServletConfiguration.class);

        // Register and map the dispatcher servlet
        ServletRegistration.Dynamic dispatcher = container.addServlet("dispatcher", new DispatcherServlet(dispatcherContext));

        dispatcher.setLoadOnStartup(1);
        dispatcher.addMapping("/");
    }
}

We also have a configuration file for the dispatcher servlet, that just sets up a view resolver and the packages to scan for components:

package com.jtuts.web.configuration;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.ViewResolver;
import org.springframework.web.servlet.view.InternalResourceViewResolver;

@Configuration
@ComponentScan(basePackages = "com.jtuts.web")
public class DispatcherServletConfiguration {

    @Bean
    ViewResolver setupViewResolver(){
        InternalResourceViewResolver resolver = new InternalResourceViewResolver();
        
        resolver.setPrefix("/WEB-INF/views/");
        resolver.setSuffix(".jsp");

        return resolver;
    }
    
}

Other then the code I showed you, we have a very simple view file for the home page. And also two basic ontrollers for the home and login page.

Result

When you deploy the project to a Tomcat 8, you get a simple login form and when you log in with the right credentials it redirects you the the home page.

login-form

Download

You can download the working project from here.

Spring Security login form integration example with XML configuration

This tutorial will show you how to integrate Spring Security into a Spring MVC application. The application won’t use a database, the user credentials are just defined as plain text in the configuration file for simplicity.

We will show you almost all of the files needed for the working application, but will only describe the parts that are strictly connected to the Spring Security integration and not just there to have a basic webapp up and running.

At the end of the tutorial you can download the whole working Maven project.

Tools used:

  • Spring Tool Suite 3.7.1.RELEASE
  • Apache Maven 3.3.9
  • Java 8
  • Tomcat 8.0.32

The project structure

Here you can see the structure of the finished project.

project-structure

Dependencies

Aside from Spring that we are using to build our webapp, we need two Spring Security related dependencies.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>
    <groupId>jtuts</groupId>
    <artifactId>spring-security-simple-integration-xml</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>war</packaging>
    <name>jtuts-spring-security-xml</name>

    <properties>

        <!-- Dependency versions -->

        <spring.version>4.2.5.RELEASE</spring.version>
        <spring.security.version>4.0.4.RELEASE</spring.security.version>

        <servlet.api.version>3.1.0</servlet.api.version>
        <jsp.version>2.0</jsp.version>

        <!-- Plugin versions -->

        <maven.compiler.plugin.version>3.5.1</maven.compiler.plugin.version>

        <!-- Misc versions -->

        <java.version>1.8</java.version>

    </properties>

    <dependencies>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.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>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>${servlet.api.version}</version>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jsp-api</artifactId>
            <version>${jsp.version}</version>
            <scope>provided</scope>
        </dependency>

    </dependencies>

    <build>
        <finalName>jtuts-spring-security-xml</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${maven.compiler.plugin.version}</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

The important things to note here:

  • spring-security-web: Contains filters and related web-security infrastructure code. You’ll need it if you require Spring Security web authentication services and URL-based access-control. This also pulls in the spring-security-core dependency.
  • spring-security-config: Contains the security namespace parsing code. You need it if you are using the Spring Security XML namespace for configuration.

The springSecurityFilterChain filter

One of the core elements of Spring Security is a chain of filters that determine if the user has access to a given resource. We define this filter in our web xml:

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" version="3.1">

    <display-name>JTuts Spring Security integration tutorial with XML configuration</display-name>

    <servlet>
        <servlet-name>mvc-dispatcher</servlet-name>
        <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
        <init-param>
            <param-name>contextConfigLocation</param-name>
            <param-value>classpath:spring/dispatcher-servlet.xml</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    <servlet-mapping>
        <servlet-name>mvc-dispatcher</servlet-name>
        <url-pattern>/</url-pattern>
    </servlet-mapping>

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>classpath:spring/application-context.xml</param-value>
    </context-param>

    <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>
    </filter-mapping>

</web-app>

Configuring Spring Security via XML

We put the XML configuration for Spring Security in spring-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-4.2.xsd
        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-4.0.xsd">

    <http use-expressions="true">
        <intercept-url pattern="/login" access="permitAll" />
        <intercept-url pattern="/**" access="hasRole('ROLE_USER')" />

        <form-login default-target-url="/home" login-page="/login" authentication-failure-url="/login?error=true" />

        <logout logout-success-url="/login" />
    </http>

    <authentication-manager>
        <authentication-provider>
            <user-service>
                <user name="admin" password="Secret123" authorities="ROLE_USER" />
            </user-service>
        </authentication-provider>
    </authentication-manager>

</beans:beans>

Here a little more explanation is needed.

  • In the http element, we define the rules and settings for our security purposes:
    • The use-expressions="true" attribute means that we can provide the access rules as expressions (like permitAll), instead of the traditional set of attributes.
    • Each intercept-url element describes one rule for our security. The first rule means that we should allow everyone to access the login page, the second rule means that all other pages are protected and need the ROLE_USER role to have access.
    • In the form-login element we specify some URLs to use for the login form.
      • default-target-url: After successful login, the user will be redirected here.
      • login-page: The URL of the login page.
      • authentication-failure-url: The URL to redirect to when authentication fails.
    • In the logout element we specify the URL to redirect to when the logout is successful.
  • In the authentication-manager element in this simple example we define the valid user credentials as plain text. There are alternative configurations available for cases when for example you would like to get user details from a database.

The XML is imported in the main application context (application-context.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:mvc="http://www.springframework.org/schema/mvc" 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.2.xsd 
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.2.xsd 
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd">
 
 	<import resource="classpath:spring/spring-security.xml"/>
 
</beans>

The login form

The view file for the login form is login.jsp:

<%@ page language="java" contentType="text/html; charset=UTF-8"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>JTuts Spring Security integration tutorial with XML configuration</title>
</head>
<body>
    <h1>Login</h1>

    <form action="${pageContext.request.contextPath}/login" method="POST">
        <table>
            <tr>
                <td><label for="username">Username:</label></td>
                <td><input type="text" name="username"></td>
            </tr>
            <tr>
                <td><label for="password">Password:</label></td>
                <td><input type="password" name="password" /></td>
            </tr>
            <tr>
                <td><input type="submit" value="Login" /></td>
            </tr>
        </table>
        <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/> 
    </form>
</body>
</html>

The important things to note here are the following:

  • The URL where we post the form (/login) is the default URL in Spring Security 4.
  • The names of the fields (username, password) are also the default names expected by Spring Security.
  • The hidden field is there because CSRF protection is enabled by default and we need a token to be able to submit the form.

Warning: In earlier versions of Spring Security the defaults mentioned could be different, so please pay attention to that if you are on an older version.

Other files

Other then the code I showed you, we have a very simple view file for the home page. And also two very simple controllers for the home and login. Also we have a dispatcher-servlet.xml where we configure the view resolver and the some other things.

Result

When you run the project, you get a simple login form and when you log in with the right credentials it redirects you the the home page.

login-form

Download

You can download the working project from here.