Spring Security - Form-Based Authentication

Last Updated : 17 Jan, 2026

Form-Based Authentication in Spring Security provides a secure and customizable way to authenticate users using a custom login page instead of the default browser login prompt. It allows better control over authentication flow, user experience, and security configurations.

  • Customizable login and logout mechanisms.
  • Protection against common security threats like session fixation and brute force attacks.
  • Seamless integration with Spring Boot and Thymeleaf.
  • Easy role-based access control configuration.

In this article, we will learn how to set up a Spring Boot application with Spring Security to implement a custom login page.

Steps to Create a Custom Login Form with Spring Security

Step 1: Create a Spring Boot Project

Use Spring Initializr to bootstrap your project with the following dependencies:

  • Spring Web: For building web applications.
  • Spring Security: For authentication and authorization.
  • Thymeleaf: For rendering HTML templates.
Spring-Initializr

Step 2: Project Structure

Your folder structure should look like this:

pro
Project Structure

Step 3: Configure pom.xml

The pom.xml defines the configuration of the dependencies of the project, we don't need to add other dependencies right now as we are using spring boot and most of the things that we need for this project are auto-configured.

pom.xml:

XML
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0"
         xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 
                        https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.4.4</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.gfg</groupId>
    <artifactId>SpringSecurityLoginForm</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>SpringSecurityLoginForm</name>
    <description>Demo project for Spring Boot</description>
    <properties>
        <java.version>17</java.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</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-thymeleaf</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

Step 4: Create the Application Class

Java
package com.gfg.SpringSecurityLoginForm;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringSecurityLoginFormApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringSecurityLoginFormApplication.class, args);
    }
}

Step 5: Create a Controller

Create a controller to handle requests for login and welcome pages.

Java
package com.gfg.SpringSecurityLoginForm.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class LoginController {

    @GetMapping("/welcome")
    public String welcome() {
        return "welcome"; // Thymeleaf template name
    }

    @GetMapping("/login")
    public String login() {
        return "login"; // Thymeleaf template name
    }
}

Step 6: Create Security Configuration

Create SpringSecurityConfig.java:

Java
package com.gfg.SpringSecurityLoginForm.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.provisioning.InMemoryUserDetailsManager;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
public class SpringSecurityConfig {

    @Bean
    public InMemoryUserDetailsManager userDetailsService() {
        UserDetails user = User.withUsername("user")
                .password("{noop}pass") // plain text password
                .roles("USER")
                .build();
        return new InMemoryUserDetailsManager(user);
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .authorizeHttpRequests(auth -> auth
                .requestMatchers("/login").permitAll()
                .anyRequest().authenticated()
            )
            .formLogin(form -> form
                .loginPage("/login")
                .defaultSuccessUrl("/welcome", true)
            )
            .logout(logout -> logout
                .logoutSuccessUrl("/login")
                .permitAll()
            );

        return http.build();
    }
}

Step 7: Create application.properties

spring.security.user.name=user

spring.security.user.password=pass

spring.thymeleaf.cache=false

spring.thymeleaf.cache=false ensures templates reload automatically during development.

Step 8: Create Templates

login.html

HTML
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org/">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1>Login page</h1>
    <form th:action="@{/login}" method="post">
        <div><label>Username: </label><input type="text" name="username"></div>
        <div><label>Password: </label><input type="password" name="password"></div>
        <div><button name="submit" type="submit" >Login</button></div>
    </form>
</body>
</html>

Welcome.html

HTML
<!DOCTYPE html>
<html xmlns:th="https://www.thymeleaf.org/">
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
    <h1>LoggedIn Successful</h1>
    <h2>Welcome Back! Click <a th:href="@{/logout}">here</a> to logout.</h2>
</body>
</html>

Step 9: Run the Application

Now it's time to run your created project, run your program as a Java application,

  • Open your browser and navigate to http://localhost:8080/welcome.
  • You will be redirected to the custom login page (http://localhost:8080/login).
  • Enter the username (user) and password (pass).
  • Upon successful login, you will be redirected to the welcome page.

After successful authentication spring will automatically redirect to the welcome page.

l
Login Page
s
Welcome Page

So, we have created a very basic custom Form-Based Authentication using spring security and tested it locally.

Comment

Explore