인자를 RequestParam으로 받아오면서 PathVariable로 요청하고 있는 멍청한 짓을 했다. 당연히 Controller에서 에러가 터졌고 ExceptionHandler 중에서 Controller 단의 에러를 핸들링하고 있는 로직이 없어서 Security 기본 ExceptionHandler에서 "머여? 에러났셔?@.@ 그럼 로그인 일단 한 번 해봐~@.@" 라며 리다이렉트 해주니...
나는 처음에는
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String token = resolveToken(request);
if (StringUtils.hasText(token) && tokenProvider.validateToken(token)) {
Authentication authentication = tokenProvider.getAuthentication(token);
SecurityContextHolder.getContext().setAuthentication(authentication);
}
filterChain.doFilter(request, response);
}
이 부분에서 Oauth의 인증로직은 건너뛰지 못하는건가? 아예 다른 패키지인가? 하고 있었는데 그게 아니었다. 그냥 애시당초 저걸로 인증 다 건너뛰고나서 에러가 터져버리니 Redirect 시켜준 것이었다. (여기서 한 1~2시간 삽질함)
👇 아래는 로그인 페이지로 리다이렉트 시켜주는 결과창
Spring Security Config에서
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.authorizeHttpRequests(req -> {
// static Resource에 대해서는 모두 허가함
req.requestMatchers(
PathRequest.toStaticResources()
.atCommonLocations()
)
.permitAll()
.requestMatchers(it -> isJwtAuthenticatedRequest(it))
.permitAll()
...
private boolean isJwtAuthenticatedRequest(HttpServletRequest request) {
String token = jwtAuthorizationFilter.resolveToken(request); // Reuse if already have this method
if (StringUtils.hasText(token) && tokenHelper.validateToken(token)) {
return true;
}
return false;
}
token을 인증해버려서 그냥 건너뛰어버리는 방법으로 구현했다. 근데 이래도 에러가 나는 것이다! 위에도 기술했듯이 애시당초 인증로직의 문제가 아니었다...
일단은
@GetMapping("/lol/{keyword}")
public List<RedisCachedGame> searchLol(
@RequestParam
String keyword) {
return searchService.cachedSearch(keyword);
}
요 부분을
@GetMapping("/lol/{keyword}")
public List<RedisCachedGame> searchLol(
@PathVariable
String keyword) {
return searchService.cachedSearch(keyword);
}
이렇게 바꿔주고나서 정상적으로 응답하는 것을 확인했다.
근데 이러고 나니 애시당초 저 redirect 로직 자체를 없애고 그냥 인증이 안됐어서 잘못된 요청이라는 응답을 보낼 방법은 없나? 라는 생각이 들었다.
DefaultAuthenticationEntryPoint 클래스를 상속받는 새 AuthenticationEntryPoint 클래스를 만들어서 Commence()
를 오버라이드해서 에러를 반환하도록 구현하는 것이다.
public class MyAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized");
}
}
그리고 SpringSecurityConfig에 CustomEntryPoint를 등록해준다.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.
...
/**
* Exception 발생시 Redirect를 하지 않고 401을 반환
*/
http.exceptionHandling(
exceptionHandlingConfigurer -> exceptionHandlingConfigurer.authenticationEntryPoint(new MyAuthenticationEntryPoint())
);
이제 아까와 동일한 에러를 발생시켜도
정상적으로 에러응답이 오는 것을 확인할 수 있다.