Spring Security을 이용하여 인증과 인가의 관련된 Handler를 다루어 보겠습니다.

1. SuccessHandler

AuthenticationSuccessHandler을 상속 받아 사용하는 SimpleUrlAuthenticationSuccessHandler를 이용하여 성공했을때 진입할 수 있는 페이지를 작성해봅니다.

@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 savedRequest = requestCache.getRequest(request, response);

        if(savedRequest != null){
            String targetUrl = savedRequest.getRedirectUrl();
            redirectStrategy.sendRedirect(request, response, targetUrl);
        }else {
            redirectStrategy.sendRedirect(request, response, getDefaultTargetUrl());
        }

    }
}

savedRequest, DefaultTargetUrl

savedRequest는 인증이 발생하기 전 페이지를 저장해두었다가, 로그인 이동 후 인증이 완료되면 다시 보여줄 화면을 말합니다. 예를 들면 로그인 안 한 상태에서 마이페이지를 클릭 후 인증을 거치면, 마이페이지 화면을 출력하게 되는 것입니다.
setDefaultTargetUrl을 통해서 아무런 save가 없다면, 홈화면으로 이동하게 해줍니다.

2. FailuerHandler

마찬가지로 부모가되는 AuthenticationFailureHandler를 상속받은 SimpleUrlAuthenticationFailureHandler로 시작하게 됩니다.

@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);
    }
}

이 외에 requestresponse를 이용하여 셋팅하셔도 됩니다.

//query parameter로 넘겨서 처리하는거 말고 아래 방식으로 처리해도 됩니다.
request.setAttribute();
response.setStatus();

3.AccessDenied

AccessDenied는 인가처리를 위한 작업을 하기위해 작성하는 겁니다.

public class CustomAccessDeniedHandler implements AccessDeniedHandler {
    private String errorPage;
    @Override
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException {
        String deniedUrl = errorPage + "?exception=" + e.getMessage();
        response.sendRedirect(deniedUrl);
    }
    // 페이지를 따로 나눌게 아니면 setter말고 하드코딩하셔도 됩니다.
    public void setErrorPage(String errorPage){ 
        this.errorPage = errorPage;
    }
}

인증? 인가?
인증 : 로그인을 하는 행위, 회원(Authenticate), 비회원(Anonymous)
인가 : 접근권한을 정하는 행위(Authorization), 회원설정페이지, 관리자페이지 등등

4.Controller Mapping

해당페이지의 컨트롤러를 작성해줍니다. 방식은 어떻게 리턴할꺼냐에 따라 달라질 수 있겠습니다.
본인이 만들어놓은 Handler에 맞게 작성하시면 됩니다.

  	@GetMapping("/login")
    public String login(
            @RequestParam(value="error", required = false) String error
            , @RequestParam(value="exception", required = false) String exception
            , Model model){

        model.addAttribute("error", error);
        model.addAttribute("exception", exception);

        return "user/login/login";
    }

    @GetMapping("/denied")
    public String accessDenied(@RequestParam(value = "exception", required = false) String exception, Model model){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        Account account = (Account) authentication.getPrincipal();
        model.addAttribute("username", account.getUsername());
        model.addAttribute("exception", exception);
        return "user/login/denied";
    }

5. WebSecurityConfigurerAdapter 설정하기

configure파일도 설정에 맞게 추가해주시면 됩니다.

    @Autowired
    private AuthenticationSuccessHandler authenticationSuccessHandler;
    @Autowired
    private AuthenticationFailureHandler authenticationFailureHandler;
    //중략...
    
       @Override
    protected void configure(final HttpSecurity http) throws Exception {

        http
        		//.antMathers()중략...
                .successHandler(authenticationSuccessHandler)
                .failureHandler(authenticationFailureHandler)
           .and()
                .exceptionHandling()
                .accessDeniedHandler(accessDeniedHandler())
                ;
        ;
    }

    @Bean
    public AccessDeniedHandler accessDeniedHandler() {
        CustomAccessDeniedHandler accessDeniedHandler = new CustomAccessDeniedHandler();
        accessDeniedHandler.setErrorPage("/denied");
        return accessDeniedHandler ;
    }
    
profile
하이

0개의 댓글

Powered by GraphCDN, the GraphQL CDN