springframework/시작하자SpringSecurity

37.AjaxAuthenticationSuccessHandler,AjaxAuthenticationFailureHandler

Jungsoomin :) 2020. 9. 29. 23:45

기본적인 흐름은 AuthenticationSuccessHandler , AutheticationFailureHandler 의 구성방법과 동일.


 

CustomAjaxAuthenticationSuccessHandler

jackson 의 ObjectMapper 를 사용하여 json 값으로 메시지를 넘긴다. HttpStatus 를 주는 점을 주목한다.

  • Authentication 객체에는 유저정보인 AjaxAuthenticationToken 이 있기 때문에(구현) 가져와 값을 참조한다.
public class CustomAjaxAuthenticationSuccessHandler implements AuthenticationSuccessHandler {

    private ObjectMapper objectMapper = new ObjectMapper();


    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {


        Account account = (Account)authentication.getPrincipal();

        response.setStatus(HttpStatus.OK.value());

        response.setContentType(MediaType.APPLICATION_JSON_VALUE);

        objectMapper.writeValue(response.getWriter(),account);// objectMapper 로 변환시킴
    }
}

CustomAjaxAuthenticationFailureHandler

jackson 의 ObjectMapper 를 사용한다. HttpStatus 코드 값과 Message 를 넘기고 있다. 

  • Exception Type 에 따라 다른 메세지를 분기한다.
public class CustomAjaxAuthenticationFailureHandler implements AuthenticationFailureHandler {

    private ObjectMapper objectMapper = new ObjectMapper();

    @Override
    public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
        String errorMessage  = "Invalid Username of Password";

        response.setStatus(HttpStatus.UNAUTHORIZED.value());

        response.setContentType(MediaType.APPLICATION_JSON_VALUE);

        if(exception instanceof UsernameNotFoundException){
            errorMessage = "Username Not Found";
        } else if (exception instanceof BadCredentialsException){
            errorMessage = "Password Not Match";
        } else if(exception instanceof DisabledException){
            errorMessage = "Locked";
        }

        objectMapper.writeValue(response.getWriter(), errorMessage);// json 으로 에러메시지 전달
    }
}

등록

SecurityConfig 클래스의 CustomAjaxAuthenticationFilter ( AbstractAuthenticationProcessingFilter 상속 ) 클래스 등록과정에서 Setter 로 해당 핸들러를 추가한다.

 

@Configuration
@EnableWebSecurity
@Order(0)
public class AjaxSecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public AuthenticationProvider ajaxAuthenticationProvider(){
        return new AjaxAuthenticationProvider();
    }

    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(ajaxAuthenticationProvider());
    }

    @Bean
    public AjaxLoginProcessingFilter ajaxLoginProcessingFilter() throws Exception {
        AjaxLoginProcessingFilter ajaxLoginProcessingFilter = new AjaxLoginProcessingFilter();
        ajaxLoginProcessingFilter.setAuthenticationManager(authenticationManagerBean());
        ajaxLoginProcessingFilter.setAuthenticationSuccessHandler(customAjaxAuthenticationSuccessHandler());
        ajaxLoginProcessingFilter.setAuthenticationFailureHandler(customAjaxAuthenticationFailureHandler());
        return ajaxLoginProcessingFilter;
    }

    @Bean
    public CustomAjaxAuthenticationSuccessHandler customAjaxAuthenticationSuccessHandler(){
        return new CustomAjaxAuthenticationSuccessHandler();
    }

    @Bean
    public CustomAjaxAuthenticationFailureHandler customAjaxAuthenticationFailureHandler(){
        return new CustomAjaxAuthenticationFailureHandler();
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .antMatcher("/api/**")
                .authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .addFilterBefore(ajaxLoginProcessingFilter(), UsernamePasswordAuthenticationFilter.class)// 해당필터 앞에 위치시킴
                .csrf().disable();

    }
}