Custom Login Page

Learn how to create custom login and logout pages.

Page creation steps

The following steps are needed to do this:

  • Design a login page and write a Thymeleaf template to match that design. The page will need a <form> to submit the username and password with two inputs that use username and password as names for the inputs.

  • Create a controller that will return the template at /login.

  • Update WebSecurityConfiguration to use the custom login page.

Let’s start with the login.html template:

Press + to interact
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:th="http://www.thymeleaf.org"
lang="en">
<head>
<meta charset="UTF-8">
<title>Taming Thymeleaf - Login</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<link rel="stylesheet" href="https://rsms.me/inter/inter.css">
<link rel="stylesheet" th:href="@{/css/application.css}">
</head>
<body>
<div class="min-h-screen bg-gray-50 flex flex-col justify-center py-12 sm:px-6 lg:px-8">
<div class="sm:mx-auto sm:w-full sm:max-w-md">
<div class="bg-white py-8 px-4 shadow sm:rounded-lg sm:px-10">
<div class="sm:mx-auto sm:w-full sm:max-w-md mb-6">
<img class="mx-auto h-12 w-auto"
th:src="@{/img/application-logo.svg}" alt="Application Logo"/>
</div>
<form th:action="@{/login}" method="post"><!--.-->
<!-- tag::logout-confirmation[] -->
<th:block th:if="${param.logout}"> <!--.-->
<div th:replace="fragments/alerts :: success(message=#{login.logout.confirmation},useHorizontalPadding=false)"></div>
</th:block>
<!-- end::logout-confirmation[] -->
<div>
<label for="username" class="block text-sm font-medium text-gray-700"
th:text="#{login.username}">
Username
</label>
<div class="mt-1 rounded-md shadow-sm">
<input id="username"
class="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-green-500 focus:border-green-500 sm:text-sm"
type="text"
required
name="username"><!--.-->
</div>
</div>
<div class="mt-6">
<label for="password" class="block text-sm font-medium leading-5 text-gray-700"
th:text="#{login.password}">
Password
</label>
<div class="mt-1 rounded-md shadow-sm">
<input id="password"
class="appearance-none block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm placeholder-gray-400 focus:outline-none focus:ring-green-500 focus:border-green-500 sm:text-sm"
type="password"
required
name="password"><!--.-->
</div>
</div>
<div class="mt-6 flex items-center justify-between">
<div class="flex items-center">
<input id="remember_me" type="checkbox"
class="h-4 w-4 text-green-600 focus:ring-green-500 border-gray-300 rounded">
<label for="remember_me" class="ml-2 block text-sm text-gray-900">
Remember me
</label>
</div>
<div class="text-sm leading-5">
<a href="#"
class="font-medium text-green-600 hover:text-green-500">
Forgot your password?
</a>
</div>
</div>
<div class="mt-6">
<span class="block w-full rounded-md shadow-sm">
<button type="submit"
class="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-green-600 hover:bg-green-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500">
Sign in
</button>
</span>
</div>
</form>
</div>
</div>
</div>
</body>
</html>
  • Spring Security expects the form’s action to be set as /login Make sure the form is set accordingly.

  • The <input> should have the username and password attribute values respectively.

Login controller

Next, let’s create ...