Spring Boot Security Custom Login Form

In this Spring Security tutorial, we will learn how to create a custom login page to implement Spring Security’s form-based authentication. By default, Spring Security provides a built-in login form to secure the web application. However, most of the time, we need to create a custom login page to meet specific requirements.

Step 1: Create a Spring Boot Project

Using Spring Initializr

  1. Navigate to Spring Initializr: Open Spring Initializr in your browser.
  2. Configure the Project:
    • Project: Maven Project
    • Language: Java
    • Spring Boot: 3.2
    • Group: com.rameshfadatare
    • Artifact: springsecuritycustomlogin
    • Name: springsecuritycustomlogin
    • Description: Demo project for Spring Boot Security Custom Login Form
    • Package name: com.rameshfadatare.springsecuritycustomlogin
    • Packaging: Jar
    • Java: 17
  3. Add Dependencies:
    • Spring Web
    • Spring Security
    • Thymeleaf
  4. Generate the Project: Click on the Generate button to download the project as a zip file.
  5. Extract the Zip File: Extract the zip file to your preferred location.

Using an IDE

  1. Open Your IDE: Open your preferred IDE (IntelliJ IDEA, Eclipse, etc.).
  2. Import the Project: Import the extracted project as a Maven project.

Step 2: Add Maven Dependencies

Ensure your pom.xml contains the necessary dependencies. It should look something like this:

<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> 

Step 3: Create the Spring Security Configuration

Create a SpringSecurityConfig class under the com.rameshfadatare.springsecuritycustomlogin.config package and add the following code:

package com.rameshfadatare.springsecuritycustomlogin.config; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.core.userdetails.User; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.core.userdetails.UserDetailsService; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.password.PasswordEncoder; import org.springframework.security.provisioning.InMemoryUserDetailsManager; import org.springframework.security.web.SecurityFilterChain; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; @Configuration public class SpringSecurityConfig { @Bean public static PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(); } @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.csrf().disable() .authorizeHttpRequests((authorize) -> authorize.anyRequest().authenticated() ).formLogin( form -> form .loginPage("/login") .loginProcessingUrl("/login") .defaultSuccessUrl("/welcome") .permitAll() ).logout( logout -> logout .logoutRequestMatcher(new AntPathRequestMatcher("/logout")) .permitAll() ); return http.build(); } @Bean public UserDetailsService userDetailsService() { UserDetails ramesh = User.builder() .username("ramesh") .password(passwordEncoder().encode("password")) .roles("USER") .build(); UserDetails admin = User.builder() .username("admin") .password(passwordEncoder().encode("admin")) .roles("ADMIN") .build(); return new InMemoryUserDetailsManager(ramesh, admin); } } 

Explanation

  1. Password Encoder: The passwordEncoder() method creates a BCryptPasswordEncoder instance for encoding passwords.
  2. Security Filter Chain: The filterChain() method configures HTTP security settings, disables CSRF protection, sets up form-based authentication with a custom login page, and configures logout.
  3. In-Memory User Details: The userDetailsService() method defines two users, ramesh and admin, and stores them in memory using InMemoryUserDetailsManager.

Step 4: Create Thymeleaf Templates

Login Page – login.html

Under the /src/main/resources/templates folder, create a login.html file and add the following content:

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Login System</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> </head> <body> <nav class="navbar navbar-expand-lg navbar-dark bg-dark"> <div class="container-fluid"> <a class="navbar-brand" th:href="@{/index}">Spring Security Custom Login Example</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> </div> </nav> <br /><br /> <div class="container"> <div class="row"> <div class="col-md-6 offset-md-3"> <div th:if="${param.error}"> <div class="alert alert-danger">Invalid Email or Password</div> </div> <div th:if="${param.logout}"> <div class="alert alert-success"> You have been logged out.</div> </div> <div class="card"> <div class="card-header"> <h2 class="text-center">Login Form</h2> </div> <div class="card-body"> <form method="post" role="form" th:action="@{/login}" class="form-horizontal"> <div class="form-group mb-3"> <label class="control-label"> Email</label> <input type="text" id="username" name="username" class="form-control" placeholder="Enter email address"/> </div> <div class="form-group mb-3"> <label class="control-label"> Password</label> <input type="password" id="password" name="password" class="form-control" placeholder="Enter password"/> </div> <div class="form-group mb-3"> <button type="submit" class="btn btn-primary">Submit</button> <span> Not registered? <a th:href="@{/register}">Register/Signup here</a> </span> </div> </form> </div> </div> </div> </div> </div> </body> </html> 

Welcome Page – welcome.html

Under the /src/main/resources/templates folder, create a welcome.html file and add the following content:

<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Welcome</title> <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous"> </head> <body> <nav class="navbar navbar-expand-lg navbar-dark bg-dark"> <div class="container-fluid"> <a class="navbar-brand" th:href="@{/index}">Spring Security Custom Login Example</a> <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav me-auto mb-2 mb-lg-0"> <li class="nav-item"> <a class="nav-link active" aria-current="page" th:href="@{/logout}">Logout</a> </li> </ul> </div> </div> </nav> <br /><br /> <div class="container"> <div class="row"> <h1> Welcome to Spring Security world!</h1> </div> </div> </body> </html> 

Step 5: Create a Spring MVC Controller

Create a WelComeController class under the com.rameshfadatare.springsecuritycustomlogin.controller package and add the following code:

package com.rameshfadatare.springsecuritycustomlogin.controller; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; @Controller public class WelComeController { @GetMapping("/welcome") public String greeting() { return "welcome"; } @GetMapping("/login") public String login(){ return "login"; } } 

Step 6: Run the Application

  1. Run the Application: Use your IDE to run the SpringsecuritycustomloginApplication class.
  2. Access the Application: Open your browser and go to http://localhost:8080. You should see the custom login page.

Testing the Custom Login Page

  1. Navigate to the Login Page: Enter http://localhost:8080 in the browser.
  2. Spring Security Custom Login Page
  3. Login: Enter a username as admin and password as admin, then click the Sign-in button.
  4. After a successful login, you will see the welcome page. Spring Security Custom Login Page

Built-In Logout Feature

Spring Security provides a built-in logout feature. Click on the logout button in the application to log out from the application.

Spring Security Custom Login Page

Conclusion

In this Spring Security tutorial, we learned how to create a custom login page to implement Spring Security’s form-based authentication. we also saw that Spring Security provided a built-in logout feature.

Leave a Comment

Scroll to Top