JwtAuthenticationFilter
라고
UsernamePasswordAuthenticationFilter.class 이전에
//로그인전 UserPasswordAuthenticationFilter 를 통해 인증을 받도록 설정
.addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);
- 항상 해당 필터를 거치도록 설정을 하였다.
초기
@Slf4j
public class JwtAuthenticationFilter extends UsernamePasswordAuthenticationFilter {
@Autowired
private PasswordEncoder passwordEncoder;
/**
* authenticationManager 수동 설정을 위함임 AbstractAuthenticationProcessingFilter에서는 authenticationManager를 설정해주지 않으면, authenticate() 메서드를 호출할 때 NullPointerException이 발생한다.
*
* @param authenticationManager : 인증 매니저
*/
public JwtAuthenticationFilter(AuthenticationManager authenticationManager) {
super();
setAuthenticationManager(authenticationManager);
}
@SneakyThrows
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
ObjectMapper objectMapper = new ObjectMapper();
LoginRequestDTO loginRequestDTO = objectMapper.readValue(request.getInputStream(), LoginRequestDTO.class);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(loginRequestDTO.getEmail(), loginRequestDTO.getPassword());
return getAuthenticationManager().authenticate(token);
}
}
- 로서 UsernamePasswordAuthenticationFilter 를 상속받아서
- 인증 수행에 대한 별도 로직을 짜주었다.
- 하지만…
- 토큰관련 통합테스트 수행후 무조건 성공할 것이라는 기대외에
- 302 라는 상태코드가 넘어오는것이 아닌가..?
- 이유는
- UsernamePasswordAuthenticationFilter 안에 있었다.
- 해당 필터의 성공시의 처리로직을 보면
@Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws ServletException, IOException { SavedRequest savedRequest = this.requestCache.getRequest(request, response); if (savedRequest == null) { super.onAuthenticationSuccess(request, response, authentication); return; } String targetUrlParameter = getTargetUrlParameter(); if (isAlwaysUseDefaultTargetUrl() || (targetUrlParameter != null && StringUtils.hasText(request.getParameter(targetUrlParameter)))) { this.requestCache.removeRequest(request, response); super.onAuthenticationSuccess(request, response, authentication); return; } clearAuthenticationAttributes(request); // Use the DefaultSavedRequest URL String targetUrl = savedRequest.getRedirectUrl(); getRedirectStrategy().sendRedirect(request, response, targetUrl); }
String targetUrl = savedRequest.getRedirectUrl(); getRedirectStrategy().sendRedirect(request, response, targetUrl);
- 요 부분의 savedRequest 는 요청에 대한 redirectUrl 가 설정되어 있지 않는다면
- 해당
스키마 : 포트
로 응답에 리다이렉트를 수행해버린다.
- 그래서 /login → 요청했더라도 → 302,
/
URI 로 자동 리다이렉트 되어 버리는 것이다.
- 해당
- 해당 필터의 성공시의 처리로직을 보면
- UsernamePasswordAuthenticationFilter 안에 있었다.
결론
- 그래서 결론..
@Slf4j public class JwtAuthenticationFilter extends OncePerRequestFilter { @Autowired private JwtProvider jwtProvider; @Autowired private UserDetailsService userDetailsService; @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String authorization = request.getHeader("Authorization"); if (!Objects.isNull(authorization)) { String atk = authorization.substring(7); try { String email = jwtProvider.extractUserEmail(atk); UserDetails userDetails = userDetailsService.loadUserByUsername(email); Authentication token = new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities()); SecurityContextHolder.getContext() .setAuthentication(token); } catch (JwtException e) { request.setAttribute("exception", e.getMessage()); } } filterChain.doFilter(request, response); } }
- OncePerRequestFilter 을 상속받는것으로 결정하였다.
- API 방식으로 필터를 구현할때는 해당 필터를 사용하면 안되었는데, 사용 용례에 대해 제대로 모르고 사용한 것 같다.
- + OncePerRequestFilter 는
- HTTP 요청당 한 번씩만 실행되도록 보장하는 추상 클래스이다.
- 서블릿이 실행되는 동안 다른 서블릿으로 요청이 전달될 수 있는데,
- 필터에서 헤더를 확인 후 특정 URL 로 포워딩을 해버리는 경우, 하나의 필터가 중복해서 여러 번 호출될 가능성이 있음.
- 이러한 중복 호출을 방지해주는 필터입니다.
- OncePerRequestFilter 을 상속받는것으로 결정하였다.
Uploaded by N2T
'자바 > Spring Security' 카테고리의 다른 글
[JWT] 리프레쉬 토큰 - 엑세스 토큰 (0) | 2024.01.19 |
---|---|
[Security] PasswordEncoder..? (0) | 2024.01.19 |
[Security] __AuthorizationFilter?__ (0) | 2024.01.19 |
[Security] `@WithAnonymousUser` 의 역할 (0) | 2024.01.14 |