protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.
...
.antMatchers("/store/**").authenticated()
.anyRequest().permitAll()
.and()
.apply(new JwtSecurityConfig(tokenProvider));
return http.build();
}
상당히 곤혹스러웠다. 디버거로도 잡히지 않는… Swagger 로 Auth 를 시도하면 또 잘 되고… 분명 프론트엔드의 문제일텐데…? 란 결론이 나기도 했다.
헌데 실상은 백엔드의 결론이었다.
이미 문제를 해결했으니 당시 상황을 재현해보면,
Security 에 걸려있지 않아 잘 들어오는 Request
Security에 걸린 문제의 Request
reqeust.getMethod() 에서 보면 OPTIONS 일 때 Authorization 토큰이 비어있는 것을 볼 수 있다. 당시 당연히 GET 일줄 알고 request.getMethod() 를 안 찍어보아 3시간을 더 소비했구나ㅋㅋ
공식가이드에 설명이 있다.
키워드를 잡고 baeldung 을 확인해보니 해결책이 있다.
https://www.baeldung.com/spring-security-cors-preflight
<aside> 💡 The cors() method will add the Spring-provided CorsFilter to the application context, bypassing the authorization checks for OPTIONS requests.
</aside>
이 가이드를 따름으로서 충분하다.
axios 와 react query 를 활용하는데, 분명히 axios 로 request 가 가며 request header 가 붙어있음에도 불구하고, 왜 백엔드에서는 request header 가 확인되지 않았을까…
프론트엔드에서는 브라우저 캐시가 OPTIONS 를 이용한 preflight 요청을 날리면 이후 그 요청을 캐싱하여 더 이상 같은 요청을 날리지 않는다.
OPTIONS 가 잘 된 경우 최초 요청의 모습
2번의 verify 가 날아갔고 그 중 한 건은 OPTIONS 이다.
이후 캐시가 동작하면, options 는 날아가지 않고 POST 만 한 번 날아간다. verify 가 한건만 날아간 것을 볼 수 있다.
list 도 마찬가지
그러고 브라우저에서 캐시를 날려버리면,
또다시 두건이 날아간다.