html form 기반의 인증 과정이 어떻게 동작하는지 알아보자.
/private
에 인증되지 않은(unauthenticated) 요청을 보낸다.FilterSecurityInterceptor
는 인증되지 않은 요청을 AccessDeniedException
예외를 던짐으로써 거부되었음을 나타낸다. ExceptionTranslationFilter
는 인증을 시작하도록 만들고 AuthenticationEtryPoint
가 구성된 로그인 페이지로 리다이렉트를 보낸다. 대부분 AuthenticationEntryPoint
는 LoginUrlAuthenticationEntryPoint
의 인스턴스이다.username, password가 넘겨지고 UsernamePasswordAuthenticationFilter
가 username과 password를 인증한다.
UsernamePasswordAuthenticationFilter
는 HttpServletRequest
에서 가져온 username과 password 인증의 하나인 UsernamepasswordAuthenticationToken
을 만든다.UsernamePasswordAuthenticationToken
은 인증하도록AuthenticationManger
에게 전달된다. AuthenticationManger
의 세부 정보는 사용자 정보가 저장되는 방식에 따라 달라진다.스프링 시큐리티 폼 로그인은 기본적으로 활성화되어 있다. 그러나 config 기반의 서블릿이 제고외는 즉시 폼 기반의 로그인은 명시적으로 제공해야 한다. 아래는 명시적으로 작성해야할 간단한 자바 config 예이다.
public SecurityFilterChain filterChain(HttpSecurity http) {
http
.formLogin(withDefaults());
// ...
}
이 config에서 스프링 시큐리티는 기본 로그인 페이지를 렌더링한다. 커스텀 로그인 페이지도 사용할 수 있다.
아래는 커스텀 로그인 폼을 제공하는 예이다.
public SecurityFilterChain filterChain(HttpSecurity http) {
http
.formLogin(form -> form
.loginPage("/login")
.permitAll()
);
// ...
}
로그인 페이지를 스프링 시큐리티 config에서 지정했다면 페이지를 렌더링해야 한다. 아래는 /login
의 html 로그인 폼을 Thymeleaf 템플릿 엔진으로 구현한 예이다.
<!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>
기본 HTML form의 몇가지 핵심 사항
/login
으로 POST 해야한다.만약 Spring MVC를 사용한다면 controller에 GET /login
와 템플릿을 매핑할 수 있도록 생성해야 한다.
@Controller
class LoginController {
@GetMapping("/login")
String login() {
return "login"; // page
}
}