Spring Security는 HTML 폼을 통해 사용자 이름과 비밀번호를 제공하는 폼 로그인(Form Login)을 지원합니다. 이 섹션에서는 Spring Security 내에서 폼 기반 인증이 어떻게 작동하는지에 대한 세부 사항을 제공합니다.
이 섹션에서는 Spring Security에서 폼 기반 로그인(form-based login)이 작동하는 방식을 살펴봅니다. 먼저 사용자가 로그인 폼으로 리디렉션되는 과정을 확인합니다.

앞서 언급된 그림은 SecurityFilterChain 다이어그램을 기반으로 설명합니다.
먼저, 사용자가 권한이 없는 리소스(/private)에 대해 인증되지 않은 요청을 보냅니다.
Spring Security의 AuthorizationFilter는 인증되지 않은 요청을 AccessDeniedException을 던지면서 거부합니다.
사용자가 인증되지 않았기 때문에 ExceptionTranslationFilter가 "Start Authentication"을 시작하고, 설정된 AuthenticationEntryPoint를 통해 로그인 페이지로 리디렉션을 보냅니다. 대부분의 경우 AuthenticationEntryPoint는 LoginUrlAuthenticationEntryPoint의 인스턴스입니다.
브라우저는 리디렉션된 로그인 페이지를 요청합니다.
애플리케이션 내에서 로그인 페이지가 렌더링됩니다.
사용자 이름과 비밀번호가 제출되면, UsernamePasswordAuthenticationFilter가 사용자 이름과 비밀번호를 인증합니다. UsernamePasswordAuthenticationFilter는 AbstractAuthenticationProcessingFilter를 확장하므로, 아래의 다이어그램은 매우 유사하게 보일 것입니다.

이 그림은 SecurityFilterChain 다이어그램을 기반으로 설명합니다.
사용자가 사용자 이름과 비밀번호를 제출하면, UsernamePasswordAuthenticationFilter가 HttpServletRequest 인스턴스에서 사용자 이름과 비밀번호를 추출하여 UsernamePasswordAuthenticationToken이라는 Authentication 타입의 토큰을 생성합니다.
다음으로, UsernamePasswordAuthenticationToken은 AuthenticationManager 인스턴스로 전달되어 인증 과정을 거칩니다. AuthenticationManager의 구체적인 동작은 사용자 정보가 저장된 방식에 따라 달라집니다.
인증이 실패한 경우, 'Failure'가 발생합니다.
인증이 성공한 경우, 'Success'가 발생합니다.
기본적으로 Spring Security의 폼 로그인이 활성화되어 있습니다. 그러나 서블릿 기반 설정이 제공되는 순간부터 폼 기반 로그인을 명시적으로 설정해야 합니다. 다음 예제는 최소한의 명시적 Java 설정을 보여줍니다.
폼 로그인
Java
public SecurityFilterChain filterChain(HttpSecurity http) {
http
.formLogin(withDefaults());
// ...
}
설명: HttpSecurity 설정을 사용하여 formLogin을 기본 설정으로 활성화합니다.
위 설정에서는 Spring Security가 기본 로그인 페이지를 렌더링합니다. 대부분의 실제 애플리케이션은 사용자 정의 로그인 폼을 필요로 합니다.
다음 설정은 사용자 정의 로그인 폼을 제공하는 방법을 보여줍니다.
사용자 정의 로그인 폼 설정
Java
public SecurityFilterChain filterChain(HttpSecurity http) {
http
.formLogin(form -> form
.loginPage("/login")
.permitAll()
);
// ...
}
설명: 이 설정에서는 /login 경로에 있는 사용자 정의 로그인 페이지를 사용하도록 지정합니다. permitAll()을 사용하여 모든 사용자가 로그인 페이지에 접근할 수 있도록 허용합니다.
Spring Security 설정에서 로그인 페이지를 지정하면, 해당 페이지를 렌더링하는 책임은 사용자에게 있습니다. 다음 Thymeleaf 템플릿은 /login 페이지에 맞는 HTML 로그인 폼을 생성합니다.
로그인 폼 - src/main/resources/templates/login.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<title>Please Log In</title>
</head>
<body>
<h1>Please Log In</h1>
<div th:if="${param.error}">
Invalid username and password.
</div>
<div th:if="${param.logout}">
You have been logged out.
</div>
<form th:action="@{/login}" method="post">
<div>
<input type="text" name="username" placeholder="Username"/>
</div>
<div>
<input type="password" name="password" placeholder="Password"/>
</div>
<input type="submit" value="Log in" />
</form>
</body>
</html>
설명: 이 Thymeleaf 템플릿은 /login 페이지에 해당하는 HTML 로그인 폼을 제공합니다.
<div th:if="${param.error}">: 로그인 오류 시 "Invalid username and password." 메시지를 표시합니다.<div th:if="${param.logout}">: 로그아웃 후 "You have been logged out." 메시지를 표시합니다.<form th:action="@{/login}" method="post">: /login 경로로 POST 요청을 보내는 폼을 설정합니다.username과 password 입력 필드를 사용하여 로그인 정보를 입력받고, "Log in" 버튼을 통해 제출합니다.기본 HTML 폼에 대한 몇 가지 주요 사항:
/login으로 POST 요청을 수행해야 합니다.username이라는 파라미터에 사용자 이름을 지정해야 합니다.password라는 파라미터에 비밀번호를 지정해야 합니다.error라는 HTTP 파라미터가 있으면, 사용자가 올바른 사용자 이름이나 비밀번호를 제공하지 않았음을 나타냅니다.logout이라는 HTTP 파라미터가 있으면, 사용자가 성공적으로 로그아웃했음을 나타냅니다.대부분의 사용자들은 로그인 페이지를 사용자 정의하는 것만으로도 충분합니다. 그러나 필요에 따라 추가 설정을 통해 앞서 설명한 모든 요소를 사용자 정의할 수 있습니다.
Spring MVC를 사용하는 경우, 우리가 생성한 로그인 템플릿과 /login GET 요청을 매핑하는 컨트롤러가 필요합니다. 다음은 최소한의 LoginController 예제입니다:
LoginController
@Controller
class LoginController {
@GetMapping("/login")
String login() {
return "login";
}
}
설명: 이 컨트롤러는 /login 경로의 GET 요청을 login 템플릿으로 매핑합니다.