개요
- 폼 인증, 인가를 성공하거나 실패한 후에 처리하고 싶은 작업을 AuthenticationSuccessHandler, AuthenticationFailureHandler, AccessDeniedHandler 를 커스텀해서 구현할 수 있다.
- AuthenticationSuccessHandler 는 인증 성공 후 처리
- AuthenticationFailureHandler 는 인증 실패 후 처리
- AccessDeniedHandler 는 인가 실패 후 처리
AuthenticationSuccessHandler 커스텀
- CustomAuthenticationSuccessHandler 클래스 구현
@Component
public class CustomAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler {
private RequestCache requestCache = new HttpSessionRequestCache();
private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
setDefaultTargetUrl("/");
SavedRequest saveRequest = requestCache.getRequest(request, response);
if(saveRequest != null){
String targetUrl = saveRequest.getRedirectUrl();
redirectStrategy.sendRedirect(request, response, targetUrl);
}else{
redirectStrategy.sendRedirect(request, response, getDefaultTargetUrl());
}
}
}
- SimpleUrlAuthenticationSuccessHandler 클래스를 상속 받고 onAuthenticationSuccess 메소드를 재정의 해준다.
- 만약 애초에 인증 페이지로 접속한 거라면, saveRequest 가 null 이기 때문에 루트 페이지로 보내고
- 만약 다른 페이지를 접속했다가 권한이 없어서 인증 페이지로 접속한 거라면, saveRequest 에 이전 요청 정보가 담기고, 인증처리가 끝난 후, 이전 요청 페이지로 이동시키는 코드이다.
AuthenticationFailureHandler 커스텀
- CustomAuthenticationFailureHandler 클래스 구현
@Component
public class CustomAuthenticationFailureHandler extends SimpleUrlAuthenticationFailureHandler {
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
String errorMessage = "Invalid Username or Password";
if(exception instanceof BadCredentialsException){
errorMessage = "Invalid Username or Password";
}else if(exception instanceof InsufficientAuthenticationException){
errorMessage = "Invalid Secret Key";
}
setDefaultFailureUrl("/login?error=true&exception=" + errorMessage);
super.onAuthenticationFailure(request, response, exception);
}
}
- SimpleUrlAuthenticationFailureHandler 클래스를 상속 받고 onAuthenticationFailure 메소드를 재정의 해준다.
- AuthenticationProvider 에서 인증이 실패하면 그 결과를 인증필터가 받아서 CustomAuthenticationFailureHandler 호출하게 된다.
- AuthenticationProvider 로 부터 받은 예외에 따라 에러메시지를 만들어주고, error, exception 을 requestParam 으로 담아서 로그인 페이지를 url 로 이동할 수 있도록 세팅한다.
- 마지막으로 부모에게 요청에 대한 처리를 넘긴다.
AccessDeniedHandler 커스텀
- CustomAccessDeniedHandler 클래스 구현
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
private String errorPage;
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException {
String deniedUrl = errorPage + "?exception=" + accessDeniedException.getMessage();
response.sendRedirect(deniedUrl);
}
public void setErrorPage(String errorPage) {
this.errorPage = errorPage;
}
}
- 인가 예외는 ExceptionTranslationFilter 가 처리한다.
- 그렇기 때문에 인가에 대한 예외도 따로 처리할 수 있는 핸들러가 필요하다. -> 그 기능을 CustomAccessDeniedHandler 가 처리해 줄 수 있다.
- 위의 코드는 ExceptionTranslationFilter 로 부터 인가 예외가 발생하면 에러 메시지를 만들고 리다이렉트하는 코드이다.
SecurityConfig 에 CustomAuthenticationSuccessHandler,CustomAuthenticationFailureHandler, AccessDeniedHandler 등록
@Configuration
@EnableWebSecurity
@Slf4j
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// ... 생략
private final AuthenticationSuccessHandler customAuthenticationSuccessHandler;
private final AuthenticationFailureHandler customAuthenticationFailureHandler;
@Override
protected void configure(final HttpSecurity http) throws Exception {
http
// ... 생략
.antMatchers("/login*").permitAll()
.and()
// ... 생략
.successHandler(customAuthenticationSuccessHandler)
.failureHandler(customAuthenticationFailureHandler)
// ... 생략
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler())
;
}
@Bean
public AccessDeniedHandler accessDeniedHandler() {
CustomAccessDeniedHandler accessDeniedHandler = new CustomAccessDeniedHandler();
accessDeniedHandler.setErrorPage("/denied");
return accessDeniedHandler;
}
}
setDefaultFailureUrl("/login?error=true&exception=" + errorMessage);
를 처리하기 위해서 "/login*"
에 대한 리소스 접근을 허용한다.
- customAuthenticationSuccessHandler, customAuthenticationFailureHandler, accessDeniedHandler 를 등록해 준다.
REFERENCES