Spring Security 기반의 애플리케이션에 아이디/패스워드 로그인 인증 후, 전달 받은 JWT를 이용해 서버 측 리소스에 접근한다고 가정해 봅시다.
이 경우, 매 요청마다 JWT를 request header에 포함해서 요청 전송을 할텐데요.
이 JWT를 JwtAuthorizationFilter가 검증할 경우, 두 가지 케이스를 테스트 해 보았습니다.
JwtAuthorizationFilter에서 인증이나 접근 권한 등의 예외를 try ~ catch로 잡는 경우
public class JwtVerificationFilter extends OncePerRequestFilter {
private final JwtTokenizer jwtTokenizer;
private final CustomAuthorityUtils authorityUtils;
public JwtVerificationFilter(JwtTokenizer jwtTokenizer,
CustomAuthorityUtils authorityUtils) {
this.jwtTokenizer = jwtTokenizer;
this.authorityUtils = authorityUtils;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// JWT 검증 시, 발생하는 예외를 try ~ catch 문으로 catch 하는 경우
try {
Map<String, Object> claims = verifyJws(request);
setAuthenticationToContext(claims);
} catch (Exception e) {
request.setAttribute("exception", e);
}
filterChain.doFilter(request, response);
}
...
...
}
- SecurityFilterChain 동작이 ExceptionTranslationFilter 까지 넘어 간다.
- ExceptionTranslationFilter에서 다시 AuthorizationFilter로 동작이 넘어간다.
- AuthorizationDecision.isGranted()이기 때문에 AccessDeniedException이 throw된다.
- ExceptionTranslationFilter에서 예외를 catch 한다.
- ExceptionTranslationFilter 내부에서 AccessDeniedException을 처리하는 로직을 수행한다.
- handleAccessDeniedException()
- 인증 여부를 체크해서 인증이 되지 않았으면 AuthenticationEntryPoint를 이용해 예외를 처리한다.
- 인증은 된 상태이고 권한이 적절하지 않다면 AccessDeniedHandler를 이용해 예외를 처리한다.
- handleAccessDeniedException()
JwtAuthorizationFilter에서 인증이나 접근 권한 등의 예외를 try ~ catch로 잡지 않는 경우
public class JwtVerificationFilter extends OncePerRequestFilter {
private final JwtTokenizer jwtTokenizer;
private final CustomAuthorityUtils authorityUtils;
public JwtVerificationFilter(JwtTokenizer jwtTokenizer,
CustomAuthorityUtils authorityUtils) {
this.jwtTokenizer = jwtTokenizer;
this.authorityUtils = authorityUtils;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
// JWT 검증 시, try ~ catch 문으로 catch 하지 않는 경우
Map<String, Object> claims = verifyJws(request);
filterChain.doFilter(request, response);
}
...
...
}
- 예외가 throw 되어서 톰캣 같은 서블릿 컨테이너 레벨까지 전파된다.
- `/error` URL로 리다이렉트 된다.
- Spring Framework의 BasicErrorController의 error() 핸들러 메서드가 `/error` 요청을 수신한다.
- 디폴트 에러 메시지를 JSON 형태로 리턴한다.
'Java Backend 개발자 되기 > Spring Security' 카테고리의 다른 글
Spring Security OAuth 2 컴포넌트 요약 (0) | 2023.01.26 |
---|---|
JWT를 이용한 인증(Authentication) 및 자격 검증(Authorization) 프로세스 (4) | 2023.01.19 |
JWT 자격 검증 시, SecurityContext는 언제 비워(clear)질까? (8) | 2023.01.19 |
Spring Security에서의 권한 부여 (Authorization) 처리 흐름 (0) | 2023.01.17 |
Spring Security에서의 인증(Authentication) 처리 흐름 (0) | 2023.01.17 |