Spring Security 5 Login Form Example

In this spring security 5 tutorial, learn to add custom login form based security to our Spring WebMVC application. I am using Spring security 5 to build this example. This tutorial additionally discusses logout from the session.

1. Include spring security 5 dependencies

Include spring security jars. I am using maven so added respective dependencies for spring security version 5.0.7.RELEASE.

<properties>
		<failOnMissingWebXml>false</failOnMissingWebXml>
		<spring.version>5.2.0.RELEASE</spring.version>
</properties>	

<!-- Spring MVC Dependency -->
<dependency>
	<groupId>org.springframework</groupId>
	<artifactId>spring-webmvc</artifactId>
	<version>${spring.version}</version>
</dependency>

<!-- Spring Security Core -->
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-core</artifactId>
	<version>${spring.version}</version>
</dependency>

<!-- Spring Security Config -->
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-config</artifactId>
	<version>${spring.version}</version>
</dependency>

<!-- Spring Security Web -->
<dependency>
	<groupId>org.springframework.security</groupId>
	<artifactId>spring-security-web</artifactId>
	<version>${spring.version}</version>
</dependency>

2. Create Spring Security Configuration

2.1. Configure Authentication and URL Security

  • I have created this simple security configuration and added two demo users ‘user‘ and ‘admin‘.
  • @EnableWebSecurity enables Spring Security’s web security support, and also provides the Spring MVC integration.
  • WebSecurityConfigurerAdapter provides a set of methods that are used to enable specific web security configuration.
  • configure(HttpSecurity http) is used to secure different URLs that need security.
  • It configures custom login page at URL /login. If username/password match then request is redirected to /home, else login page is refreshed with respective error message.
  • It also configures logout from session. After logout, user is redirected to login page again.

I have used in-memory authentication using auth.inMemoryAuthentication(). You can configure JDBC auth using auth.jdbcAuthentication() or LDAP auth using auth.ldapAuthentication().

package com.howtodoinjava.demo.spring.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
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;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	PasswordEncoder passwordEncoder;

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.inMemoryAuthentication()
		.passwordEncoder(passwordEncoder)
		.withUser("user").password(passwordEncoder.encode("123456")).roles("USER")
		.and()
		.withUser("admin").password(passwordEncoder.encode("123456")).roles("USER", "ADMIN");
	}

	@Bean
	public PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
		.antMatchers("/login")
			.permitAll()
		.antMatchers("/**")
			.hasAnyRole("ADMIN", "USER")
		.and()
			.formLogin()
			.loginPage("/login")
			.defaultSuccessUrl("/home")
			.failureUrl("/login?error=true")
			.permitAll()
		.and()
			.logout()
			.logoutSuccessUrl("/login?logout=true")
			.invalidateHttpSession(true)
			.permitAll()
		.and()
			.csrf()
			.disable();
	}
}

Read More: Spring Security XML Config for Login Form

2.2. Bind spring security to web application

In Spring web applications, security is implemented using DelegatingFilterProxy. To register it, with spring container in Java configuration, you shall use AbstractSecurityWebApplicationInitializer.

The spring will detect the instance of this class during application startup, and register the DelegatingFilterProxy to use the springSecurityFilterChain before any other registered Filter. It also register a ContextLoaderListener.

package com.howtodoinjava.demo.spring.config;

import org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer;
public class SpringSecurityInitializer extends AbstractSecurityWebApplicationInitializer {
	//no code needed
}

Also, include SecurityConfig to AppInitializer.

package com.howtodoinjava.demo.spring.config;

import org.springframework.web.servlet.support.AbstractAnnotationConfigDispatcherServletInitializer;

public class AppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {

   @Override
   protected Class<?>[] getRootConfigClasses() {
      return new Class[] { HibernateConfig.class, SecurityConfig.class };
   }

   @Override
   protected Class<?>[] getServletConfigClasses() {
      return new Class[] { WebMvcConfig.class };
   }

   @Override
   protected String[] getServletMappings() {
      return new String[] { "/" };
   }
}

3. Add Custom Login Form

3.1. Login Controller

Add the login controller method to handle login and logout requests.

package com.howtodoinjava.demo.spring.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

@Controller
public class LoginController 
{
	@RequestMapping(value = "/login", method = RequestMethod.POST)
    public String loginPage(@RequestParam(value = "error", required = false) String error, 
    						@RequestParam(value = "logout", required = false) String logout,
    						Model model) {
		String errorMessge = null;
		if(error != null) {
			errorMessge = "Username or Password is incorrect !!";
		}
		if(logout != null) {
			errorMessge = "You have been successfully logged out !!";
		}
		model.addAttribute("errorMessge", errorMessge);
        return "login";
    }
 
    @RequestMapping(value="/logout", method = RequestMethod.GET)
    public String logoutPage (HttpServletRequest request, HttpServletResponse response) {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth != null){    
            new SecurityContextLogoutHandler().logout(request, response, auth);
        }
        return "redirect:/login?logout=true";
    }
}

3.2. login.jsp

Create login.jsp file which will accept username and password; and post them to URL /login.

<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<html>
<body onload='document.loginForm.username.focus();'>
	<h1>Spring Security 5 - Login Form</h1>

	<c:if test="${not empty errorMessge}"><div style="color:red; font-weight: bold; margin: 30px 0px;">${errorMessge}</div></c:if>

	<form name='login' action="/login" method='POST'>
		<table>
			<tr>
				<td>UserName:</td>
				<td><input type='text' name='username' value=''></td>
			</tr>
			<tr>
				<td>Password:</td>
				<td><input type='password' name='password' /></td>
			</tr>
			<tr>
				<td colspan='2'><input name="submit" type="submit" value="submit" /></td>
			</tr>
		</table>
		<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
	</form>
</body>
</html>

4. Spring Security 5 Login Form Demo

  1. Start the application with maven run command tomcat7:run. Launch homepage http://localhost:8080/home. It will redirected to login page http://localhost:8080/login.

    Login Form
    Login Form
  2. Enter INCORRECT username or password. A login error message will be displayed.

    Incorrect username or password
    Incorrect username or password
  3. Enter CORRECT username and password combination. user and 123456. Home page will be displayed.

    Home Page
    Home Page
  4. Click on logout button. The user will be logged out and redirected back to the login page.

    Logged Out
    Logged Out

Happy Learning !!

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

6 thoughts on “Spring Security 5 Login Form Example”

  1. The sample code given has home.jsp but nothing relates to the output when we execute the GitHub checkout, it will not work correctly.
    Can you please correct the sample to match like to show in the output?

    Reply
  2. I face the same issue, I sout the login controller to see whether it is redirecting to another page or not. I found out that it’s redirecting to the same page again and again.

    Reply
  3. Tried running the code.
    After login, the login page is being displayed again and again with no redirection to homepage.

    Reply

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.