Form Login

A Custom Login Page

The generated login page is fine for testing; real sites use their own. Point Spring Security to your page and make it public:

@Bean
SecurityFilterChain webChain(HttpSecurity http) throws Exception {
    http
        .authorizeHttpRequests(auth -> auth
            .requestMatchers("/", "/products/**").permitAll()
            .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll()
            .anyRequest().authenticated())
        .formLogin(form -> form
            .loginPage("/login")                     // GET /login shows YOUR page
            .loginProcessingUrl("/login")            // POST /login is handled by Spring (default)
            .usernameParameter("email")              // form field names
            .passwordParameter("password")
            .defaultSuccessUrl("/account", false)    // false = go back to the saved page if there is one
            .failureUrl("/login?error")
            .permitAll());                           // everyone may see the login page
    return http.build();
}

@Controller
class LoginController {
    @GetMapping("/login")
    String login() { return "login"; }               // templates/login.html
}

The Thymeleaf Template

<form th:action="@{/login}" method="post">
  <div th:if="${param.error}" class="alert">Invalid email or password.</div>
  <div th:if="${param.logout}" class="info">You have been logged out.</div>

  <input type="email" name="email" placeholder="Email" required>
  <input type="password" name="password" placeholder="Password" required>
  <!-- th:action adds the hidden _csrf field automatically -->
  <button type="submit">Sign in</button>
</form>

Note: Your controller never checks the password. UsernamePasswordAuthenticationFilter intercepts POST /login before any controller and runs the authentication flow.

What the Browser Sees

Example

Success and failure of a form login:

POST /login HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Cookie: JSESSIONID=1A2B...

email=asha%40gmail.com&password=asha123&_csrf=9d4c2f1e-...

Example output

Correct password:
HTTP/1.1 302
Location: http://localhost:8080/account
Set-Cookie: JSESSIONID=7F3E...; Path=/; HttpOnly     (new id: session fixation protection)

Wrong password:
HTTP/1.1 302
Location: http://localhost:8080/login?error