1. Handler 구현
public class MemberAuthenticationHandler {
@Slf4j
public static class Success implements AuthenticationSuccessHandler {
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response,
Authentication authentication) throws IOException {
... // 인증 성공 시, 로깅 또는 response로 사용자 정보 전송 등의 작업
}
}
@Slf4j
public static class Failure implements AuthenticationFailureHandler{
@Override
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response,
AuthenticationException exception) throws IOException {
... // 인증 실패 시, 로깅 또는 response로 사용자 정보 전송 등의 작업
}
}
}
2. Security Configuration
SecurityConfig에서 커스텀 필터 설정을 해주었던 CustomFilterConfigurer에 핸들러를 설정했다.
public class CustomFilterConfigurer extends AbstractHttpConfigurer<CustomFilterConfigurer, HttpSecurity> {
@Override
public void configure(HttpSecurity builder) throws Exception {
...
// SuccessHandler, FailureHandler 각각 구현 클래스 생성 -> DI가 아닌 new도 무방하다
jwtAuthenticationFilter.setAuthenticationSuccessHandler(new MemberAuthenticationHandler.Success());
jwtAuthenticationFilter.setAuthenticationFailureHandler(new MemberAuthenticationHandler.Failure());
...
}
}
3. AuthenticationFilter
인증 성공 시 호출되는 successfulAuthentication(...)에 핸들러를 추가했다.
실패 시 failureHandler는 알아서 호출되므로 별도로 추가할 필요는 없다.
@Override
protected void successfulAuthentication(HttpServletRequest request,
HttpServletResponse response,
FilterChain chain,
Authentication authResult) throws ServletException, IOException {
...
this.getSuccessHandler().onAuthenticationSuccess(request, response, authResult);
}
4. 테스트
1) 인증 성공
나는 성공 시 httpStatus는 200(OK)로 내보내고,
API 응답 코드(status), 메세지(message), 데이터(data)를 함께 내보낸다.
data에는 멤버 기본 정보를 함께 내보내도록 구현했다.
성공 시 멤버 정보와, 토큰이 함께 잘 나가는 것을 확인할 수 있었다.
2) 인증 실패
실패 시 httpStatus는 401(Unauthorized),
알맞은 status와 message를 내보내도록 구현했다.
(data에 null을 함께 보낼까 생각하고 있다)
예상한 응답값이 잘 나갔고, 헤더에는 토큰 정보가 전혀 나가지 않는 것을 확인했다.
3) 토큰 만료 시 (추가)
io.jsonwebtoken.ExpiredJwtException
이 발생했다!
5. 힘들었던 점
작성 중에 글이 다 날아간 점...^^ 한 번 날리고 쓰는 글은 역시 느낌이 다르다.
그리고 JWT 생성 또한 핸들러에서 처리할 건지 그대로 필터에서 처리할 건지 역할 분담에 대해 고민했다.
사실 아직까지도 논리적 근거를 가진 답을 못 내리는 이유는 필터의 역할에 대해 정확히 알지 못해서인 것 같다.
JWT 생성은 JwtTokenizer가 담당 하지만 이 생성 시점을 어디에 둬야 할 지가 고민거리였다. (이다)
비록 필터 클래스에서 authenticate() 한 줄로 인증을 요청한다 해도, 내부적으로 처리가 위임되며(manager, provier, service...) 많은 로직을 거쳐 사용자 인증을 하는데
성공/실패 여부를 얻는 것 까지가 필터의 역할이고
그 후 작업할 일은 핸들러에서 맡는게 나은 것 같다고 생각은 한다.
뭐가 더 올바른 역할분담인지는 확신하기 힘들다😓
+ 욕심이 생겨 성공 시 response에 멤버 정보를 함께 담아주도록 추가 구현을 했는데
이 때도 인증 정보의 principal을 사용한다.
principal을 get해오면서 어? 토큰 만들 때도 가져와서 썼었는데 하는 생각이 들었다.
이렇게 되면 토큰 생성하는 작업도 필터에서 빼내오면 좋지 않을까 싶다.
++ 막 구현하다 보니 리팩토링이 필요한 부분이 많이 보인다.
우선 이건 시간상 프리 프로젝트에 적용하면서 한 번 더 익힌 뒤에 정리하면 좋지 않을까 싶다^^;;;;;;
'공부기록 > SPRING' 카테고리의 다른 글
죽음의 CORS ERROR (5) | 2023.03.01 |
---|---|
JWT 토큰 인증 (0) | 2023.02.19 |
Spring Security - JWT 인증 적용기 (1) 로그인 시 사용자 인증, JWT 발급 (0) | 2023.02.17 |
Spring Data JPA | InvalidDataAccessApiUsageException: "detached entity passed to (5) | 2023.01.11 |
[JUnit] Required String parameter '???' is not present (0) | 2023.01.04 |
댓글