In this article, I would like to share with you how to code a custom login page in a Spring Boot application with Thymeleaf as the default template engine, HTML 5 for built-in support for field validation, and Bootstrap 4 for responsive user interface.

When Spring Security API is present in the classpath, it will generate the default login page that looks as follows:

spring default login form

This default login is suitable only for quick test, and in practice we almost need to have a custom login page that matches the application’s UI and requires other customizations. The code example below will create a custom login page that looks like the following:

spring custom login form

In this custom login page, we have a logo, a headline text, two fields email and password, a checkbox Remember me and a button Login.

 

1. Configure Custom Login Page in Spring Security Configuration Class

First, you need to specify URL of the custom login page in the Spring Security configuration class as follows:

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.authorizeRequests()
			.anyRequest().authenticated()
			...
			.formLogin()
				.loginPage("/login")
				.usernameParameter("email")
				.permitAll()
			.and()
			.logout().permitAll()
			.and().rememberMe()
				.tokenRepository(persistentTokenRepository())
			...

	}

}

As you can see, the login page URL is /login, so you need to have a handler method for this URL in a Spring MVC controller. For example:

@Controller
public class CommonController {

	...
	
	@GetMapping("/login")
	public String viewLoginPage() {
		// custom logic before showing login page...
		
		return "login";
	}
}

As you can see, the handler method returns the logical view name login which will be resolved to the login.html file by Thymeleaf template engine.

If you don’t have any custom logic that needs to be performed before showing the login page, you can simply specify the view name resolution in a Spring MVC configuration class as shown in the code snippet below:

@Configuration
public class MvcConfig implements WebMvcConfigurer {

	@Override
	public void addViewControllers(ViewControllerRegistry registry) {
		registry.addViewController("/login").setViewName("login");
	}
}

You can also note that we use different name for the username field in the custom login form, e.g. email:

.formLogin()
	.loginPage("/login")
	.usernameParameter("email")

Check this article for more customizations of the form login. This article focuses on the code of the custom login page only.

 

2. Code Custom Login Page with Thymeleaf, HTML and Bootstrap

For your reference, below is the full code of the custom login page – login.html under src/main/resources/templates directory (all the CSS classes are from Bootstrap):

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
	<title>Login - Shopme Admin</title>
	<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" 
		integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" 
		crossorigin="anonymous" />
</head>
<body>
<div class="container-fluid text-center">
	<div>
		<img class="img-fluid" th:src="/@{/images/ShopmeAdminBig.png}" />
	</div>
	<form th:action="@{/login}" method="post" style="max-width: 350px; margin: 0 auto;">
	
		<div th:if="${param.error}">
			<p class="text-danger">[[${session.SPRING_SECURITY_LAST_EXCEPTION.message}]]</p>
		</div>
		
		<div th:if="${param.logout}">
			<p class="text-warning">You have been logged out.</p>
		</div>
		
		<div class="border border-secondary p-3 rounded">
			<p>Access to Shopme Control Panel</p>
			<p>
				<input type="email" name="email" class="form-control" placeholder="E-mail" required autofocus/>
			</p>
			<p>
				<input type="password" name="password" class="form-control" placeholder="Password" required />
			</p>
			<p>
				<input type="checkbox" name="remember-me" />&nbsp;Remember Me
			</p>
			<p>
				<input type="submit" value="Login" class="btn btn-primary" />
			</p>
		</div>
	</form>		
</div>
</body>
</html>

You should declare a XML namespace so you can use Thymeleaf tags and attributes with the prefix th in the HTML document:

<html xmlns:th="http://www.thymeleaf.org">

The following meta tag will make the page responsive on different devices:

<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0">

The following link for using Bootstrap version 4.4.1 from a CDN website:

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" 
	integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" 
	crossorigin="anonymous" />

To display the logo image, you should put an image file under the src/main/resources/static/images directory:

<img class="img-fluid" th:src="/@{/images/ShopmeAdminBig.png}" />

For the input fields, we use field type email and password so the browser will validate the email automatically. And use the attribute required for both email and password so the browser will check fields not empty:

<input type="email" name="email" class="form-control" placeholder="E-mail" required autofocus/>
<input type="password" name="password" class="form-control" placeholder="Password" required />

So with HTML 5, you don’t have to write a single line of Javascript code to validate the form. Very convenient!

And note that, to display the original error message in case failed login, you should print message of the SPRING_SECURITY_LAST_EXCEPTION object from the session like this:

<div th:if="${param.error}">
	<p class="text-danger">[[${session.SPRING_SECURITY_LAST_EXCEPTION.message}]]</p>
</div>

 

That’s code example of a Spring Security custom login page with Thymeleaf, HTML 5 and Bootstrap. To see the coding in action, you can watch the following video:

 

Related Spring Security Tutorials:

 

Other Spring Boot Tutorials:


About the Author:

is certified Java programmer (SCJP and SCWCD). He began programming with Java back in the days of Java 1.4 and has been passionate about it ever since. You can connect with him on Facebook and watch his Java videos on YouTube.



Add comment

   


Comments 

#4James2022-10-24 04:49
This is not helpful, the codes were hidden so that beginners can get confused.
Quote
#3Sunil manawadkar2021-03-18 00:41
i need comment system code in spring boot thymleaf .
Quote
#2Nam2020-12-22 00:46
Hi youngchange,
You need to have the Spring boot starter security dependency present in the project's classpath.
Quote
#1yongchang2020-12-16 21:09
it will be best if you include the dependency we need
Quote