This version is still in development and is not considered stable yet. For the latest stable version, please use Spring Security 6.4.1!spring-doc.cn

Form Login

Spring Security provides support for username and password being provided through an HTML form. This section provides details on how form based authentication works within Spring Security.spring-doc.cn

This section examines how form-based login works within Spring Security. First, we see how the user is redirected to the login form:spring-doc.cn

loginurlauthenticationentrypoint
Figure 1. Redirecting to the Login Page

The preceding figure builds off our SecurityFilterChain diagram.spring-doc.cn

number 1 First, a user makes an unauthenticated request to the resource (/private) for which it is not authorized.spring-doc.cn

number 2 Spring Security’s AuthorizationFilter indicates that the unauthenticated request is Denied by throwing an AccessDeniedException.spring-doc.cn

number 3 Since the user is not authenticated, ExceptionTranslationFilter initiates Start Authentication and sends a redirect to the login page with the configured AuthenticationEntryPoint. In most cases, the AuthenticationEntryPoint is an instance of LoginUrlAuthenticationEntryPoint.spring-doc.cn

number 4 The browser requests the login page to which it was redirected.spring-doc.cn

number 5 Something within the application, must render the login page.spring-doc.cn

When the username and password are submitted, the UsernamePasswordAuthenticationFilter authenticates the username and password. The UsernamePasswordAuthenticationFilter extends AbstractAuthenticationProcessingFilter, so the following diagram should look pretty similar:spring-doc.cn

usernamepasswordauthenticationfilter
Figure 2. Authenticating Username and Password

The figure builds off our SecurityFilterChain diagram.spring-doc.cn

number 1 When the user submits their username and password, the UsernamePasswordAuthenticationFilter creates a UsernamePasswordAuthenticationToken, which is a type of Authentication, by extracting the username and password from the HttpServletRequest instance.spring-doc.cn

number 2 Next, the UsernamePasswordAuthenticationToken is passed into the AuthenticationManager instance to be authenticated. The details of what AuthenticationManager looks like depend on how the user information is stored.spring-doc.cn

number 3 If authentication fails, then Failure.spring-doc.cn

  1. The SecurityContextHolder is cleared out.spring-doc.cn

  2. RememberMeServices.loginFail is invoked. If remember me is not configured, this is a no-op. See the RememberMeServices interface in the Javadoc.spring-doc.cn

  3. AuthenticationFailureHandler is invoked. See the AuthenticationFailureHandler class in the Javadocspring-doc.cn

number 4 If authentication is successful, then Success.spring-doc.cn

  1. SessionAuthenticationStrategy is notified of a new login. See the SessionAuthenticationStrategy interface in the Javadoc.spring-doc.cn

  2. The Authentication is set on the SecurityContextHolder. See the SecurityContextPersistenceFilter class in the Javadoc.spring-doc.cn

  3. RememberMeServices.loginSuccess is invoked. If remember me is not configured, this is a no-op. See the RememberMeServices interface in the Javadoc.spring-doc.cn

  4. ApplicationEventPublisher publishes an InteractiveAuthenticationSuccessEvent.spring-doc.cn

  5. The AuthenticationSuccessHandler is invoked. Typically, this is a SimpleUrlAuthenticationSuccessHandler, which redirects to a request saved by ExceptionTranslationFilter when we redirect to the login page.spring-doc.cn

By default, Spring Security form login is enabled. However, as soon as any servlet-based configuration is provided, form based login must be explicitly provided. The following example shows a minimal, explicit Java configuration:spring-doc.cn

Form Login
public SecurityFilterChain filterChain(HttpSecurity http) {
	http
		.formLogin(withDefaults());
	// ...
}
<http>
	<!-- ... -->
	<form-login />
</http>
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
	http {
		formLogin { }
	}
	// ...
}

In the preceding configuration, Spring Security renders a default login page. Most production applications require a custom login form.spring-doc.cn

The following configuration demonstrates how to provide a custom login form.spring-doc.cn

Custom Login Form Configuration
public SecurityFilterChain filterChain(HttpSecurity http) {
	http
		.formLogin(form -> form
			.loginPage("/login")
			.permitAll()
		);
	// ...
}
<http>
	<!-- ... -->
	<intercept-url pattern="/login" access="permitAll" />
	<form-login login-page="/login" />
</http>
open fun filterChain(http: HttpSecurity): SecurityFilterChain {
	http {
		formLogin {
			loginPage = "/login"
			permitAll()
		}
	}
	// ...
}

When the login page is specified in the Spring Security configuration, you are responsible for rendering the page. The following Thymeleaf template produces an HTML login form that complies with a login page of /login.:spring-doc.cn

Login Form - src/main/resources/templates/login.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
	<head>
		<title>Please Log In</title>
	</head>
	<body>
		<h1>Please Log In</h1>
		<div th:if="${param.error}">
			Invalid username and password.</div>
		<div th:if="${param.logout}">
			You have been logged out.</div>
		<form th:action="@{/login}" method="post">
			<div>
			<input type="text" name="username" placeholder="Username"/>
			</div>
			<div>
			<input type="password" name="password" placeholder="Password"/>
			</div>
			<input type="submit" value="Log in" />
		</form>
	</body>
</html>

There are a few key points about the default HTML form:spring-doc.cn

  • The form should perform a post to /login.spring-doc.cn

  • The form needs to include a CSRF Token, which is automatically included by Thymeleaf.spring-doc.cn

  • The form should specify the username in a parameter named username.spring-doc.cn

  • The form should specify the password in a parameter named password.spring-doc.cn

  • If the HTTP parameter named error is found, it indicates the user failed to provide a valid username or password.spring-doc.cn

  • If the HTTP parameter named logout is found, it indicates the user has logged out successfully.spring-doc.cn

Many users do not need much more than to customize the login page. However, if needed, you can customize everything shown earlier with additional configuration.spring-doc.cn

If you use Spring MVC, you need a controller that maps GET /login to the login template we created. The following example shows a minimal LoginController:spring-doc.cn

LoginController
@Controller
class LoginController {
	@GetMapping("/login")
	String login() {
		return "login";
	}
}
@Controller
class LoginController {
    @GetMapping("/login")
    fun login(): String {
        return "login"
    }
}