Custom Login Form in Spring Security
In this post, We will take a look at providing a custom form login in a spring boot application.
The default spring boot form login may not fit everyone’s need. For example, Some organization may want to put a logo on their login page. Some may find the default login forms less appealing. For some perfectionists, The default password may not seem to fit the theme of the whole application. So it makes sense if someone wants to provide their implementation of the login page.
The idea here is that the path /login
should return an HTML containing a form. To achieve that, We first need to add thymeleaf support and configure a custom login page.
Add thymeleaf view support
Add thymeleaf starter as dependency. We need this starter because Spring MVC need a view resolver to map a path to a view template.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Code language: HTML, XML (xml)
Custom Spring Boot login page
Create a file called src/main/resources/views/login.html
For this, I have created a simple HTML with the following content.
<!DOCTYPE html>
<html lang="en" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.0.2/tailwind.min.css">
<title>Login : Demo</title>
</head>
<body class="h-screen">
<div class="container mx-auto h-full flex justify-center items-center text-green-700 px-4">
<div class="md:w-1/3 shadow-xl rounded-2xl border bg-green-100 w-full">
<h1 class="text-center font-medium text-2xl text-white rounded-t-2xl bg-green-500 py-4">Sign In</h1>
<form th:action="@{/login}" method="post" class="border-teal p-4 border-t-12 bg-white mb-6">
<div class="mb-4">
<label for="username" class="font-bold text-lg block mb-2">Username</label>
<input id="username" type="text" name="username" autocomplete="off"
class="block w-full rounded p-2 rounded shadow border focus:outline-none focus:ring-2 focus:ring-green-600 focus:border-transparent"
placeholder="Your Username">
</div>
<div class="mb-4">
<label for="password" class="font-bold text-lg block mb-2">Password</label>
<input id="password" type="password" name="password" autocomplete="off"
class="block w-full rounded p-2 rounded shadow border focus:outline-none focus:ring-2 focus:ring-green-600 focus:border-transparent"
placeholder="Your Password">
</div>
<div class="flex items-center justify-between">
<input class="bg-green-500 text-white text-lg font-medium p-2 rounded inline-block w-full hover:bg-green-400 transition duration-400 hover:shadow-lg"
type="submit" value="Login">
</div>
</form>
<div class="text-center pb-4">
<p class="text-grey-dark text-sm">
Don't have an account? <a href="#" class="no-underline text-green-500 font-bold">Create an Account</a>.
</p>
</div>
</div>
</div>
</body>
</html>
Code language: HTML, XML (xml)
Configure Spring MVC Login Path
Map this login.html
to the path /login
. For this step, you need to provide a custom WebMvcConfigurer
to let spring MVC know that you are registering a new mapping for login
as shown below.
package com.springhow.examples.springboot.security.customformlogin.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("login");
}
}
Code language: JavaScript (javascript)
By doing this configuration, The MVC context will look for login.html
under src/main/resources/templates/
whenever a request comes to /login
.
Spring Security java configuration
Finally, override the default HttpSecurity
configuration as shown below.
package com.springhow.examples.springboot.security.customformlogin.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.and()
.logout()
.permitAll();
}
}
Code language: JavaScript (javascript)
Verify custom Form login
If all the above are done correctly, Then on requesting http://localhost:8080/hello
would redirect to a custom login page as shown below.
You can find the code for this project in this github link. Feel free checkout the code and play with it.
If you liked this article, you may also find the following write-ups interesting.
In case of password/username wrong the page is refreshed but no error message appears