인프런에서 진행하는 정수원 강사님의 "스프링 시큐리티 - Spring Boot 기반으로 개발하는 Spring Security" 강의를 보고 학습을 위해 개인적으로 추가/정리한 글임을 알립니다.
[ Login 인증 ] UsernamePasswordAuthenticationFilter
SecurityContext
: 인증 필터가 사용자의 인증을을 가지고 있는 Context
SecurityContextHolder.getContext().getAuthentication()
: 어디서든 현재 어떤 인증을 받았는지 볼 수 있다.
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/login.html") // 사용자 정의 로그인 페이지
.defaultSuccessUrl("/home") // 로그인 성공 후 이동 페이지
.failureUrl("/login.html?error=true") // 로그인 실패 후 이동 페이지
.usernameParameter("username") // 아이디 파라미터명 설정
.passwordParameter("password") // 패스워드 파라미터명 설정
.loginProcessingUrl("/login") // 로그인 Form Action Url
.successHandler(loginSuccessHandler()) // 로그인 성공 후 핸들러
.failureHandler(loginFailureHandler()) // 로그인 실패 후 핸들러
;
}
// 실제 사용 코드
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.anyRequest().authenticated();
http
.formLogin()
.loginPage("/loginPage") // 직접 만든 로그인 페이지로 이동하도록 설정
.defaultSuccessUrl("/")
.failureUrl("/login")
.usernameParameter("userId")
.passwordParameter("passwd")
.loginProcessingUrl("/login_proc")
.successHandler(new AuthenticationSuccessHandler() { // 로그인 성공 시 호출하는 핸들러
// handler
})
.failureHandler(new AuthenticationFailureHandler() { // 로그인 실패 시 호출하는 핸들러
// handler
})
.permitAll() // 로그인 페이지는 인증을 받지 않아도 되도록.
;
}
> 인증과정
Request가 들어오면 UsernamePasswordAuthenticationFilter
로 들어오게 되고 Authentication
(Username + Password) 객체를 AuthenticationManager
로 보낸다.
AuthenticationManager
는 AuthenticationProvider
에게 인증처리를 맡기고, 인증에 실패하면 예외를 발생하고 인증에 성공하면 다시 AuthenticationManager
가 필터에게 전달해서 Authentication(User + Authorities) 객체를 넘기면 이 정보를 SecurityContext
에 저장하고 SuccessHandler
로 이후 작업을 수행한다.
FilterChainProxy
는 Filter를 관리하는 Bean인데 이 프록시가 가지는 여러 기본적인 필터 Bean들이 있다.
.formLogin()
을 실행하면 여러 API에 관련된 필터들이 생성이 된다. 그래서 이 FilterChainProxy
는 각각의 필터들을 순서대로 사용자 요청을 처리할 수 있도록 호출해준다.
[ Logut 처리 ] LogoutFilter
Logout 요청(/logout
)이 들어오면 Security가 이 요청을 받고 로그아웃 처리를 한다.
- 세션을 무효화하고
- 인증토큰을 삭제하고 (
SecurityContext
등) - 쿠키정보도 삭제하고
- 로그인 페이지로 리다이렉트
의 순서로 진행된다.
protected void configure(HttpSecurity http) throws Exception {
http.logout() // 로그아웃 처리
.logoutUrl("/logout") // 로그아웃 처리 URL
.logoutSuccessUrl("/login") // 로그아웃 성공 후 이동 페이지
.deleteCookies("JSESSIONID", "remember-me") // 로그아웃 후 쿠키 삭제
.addLogoutHandler(logoutHandler()) // 로그아웃 핸들러
.logoutSuccessHandler(logoutSuccessHandler()) // 로그아웃 성공 후 핸들러
;
}
// 실제 사용 코드
protected void configure(HttpSecurity http) throws Exception {
http
.logout()
.logoutUrl("/logout") // default 는 logout , SpringSecurity는 기본적으로는 post방식으로 logout처리한다.
.logoutSuccessUrl("/login") // logout후 이동할 페이지를 설정
.addLogoutHandler(new LogoutHandler() {
@Override
public void logout(HttpServletRequest request, HttpServletResponse response, Authentication authentication) {
HttpSession session = request.getSession();
session.invalidate();
}
})
.logoutSuccessHandler(new LogoutSuccessHandler() { // logout 후 호출하는 핸들러
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.sendRedirect("/login");
}
})
.deleteCookies("remember-me") // remember-me 라는 쿠키가 삭제된다.
;
}
> 인증과정
기본적으로는 POST 방식으로 Request를 받아서 해당 요청은 LogoutFilter
로 이동한다.
Filter는 SecurityContext
로부터 Authentication
객체를 꺼내와서 SecurityContextLogoutHandler
로 가져온다.
이 핸들러가 세션을 무효화 하고, 쿠키를 삭제하고 SecurityContextHolder.clearContext()
를 수행한다.
(get 방식으로 로그아웃을 처리할 때도 이 SecurityContextLogoutHandler
에서 처리한다.)
로그아웃 핸들러가 성공적으로 종료되면 SimpleUrlLogoutSuccessHandler
가 login페이지로 리다이렉트 해준다.
다음 시간에는 Spring Security 에서 제공하는 Remember Me 인증 API에 대해서 알아볼 것이다.
'웹 프로그래밍 > [ Spring Security ]' 카테고리의 다른 글
[ Spring Security ] 05. 인증/인가 API의 예외처리 (0) | 2021.12.12 |
---|---|
[ Spring Security ] 04. 인가 API와 표현식 (0) | 2021.12.09 |
[ Spring Security ] 03. 동시 세션제어와 세션 고정보호, 세션 정책 관리 (0) | 2021.12.08 |
[ Spring Security ] 02. 익명 사용자 인증처리 필터 : AnonymousAuthenticationFilter (0) | 2021.12.08 |
[ Spring Security ] 01. Remember-Me 인증이란? (0) | 2021.12.07 |