0. 들어가기 전에
예전에 진행하던 프로젝트를 유지보수하던 중에 CORS 정책이 wildcard로 열려있는 것을 확인해 보안을 위해서 wildcard를 없애던 중 마주쳤던 문제입니다.
1. AS-IS
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*");
}
기존 Cors관련 메서드는 이런 식으로 와일드 카드로 열려있었다. 와일드 카드는 보안 상 안좋기도 하고 나중에 쿠키를 사용하려면 변경해야하기 때문에 이번 기회에 아래처럼 변경해보기로 했다.
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("URL1", "URL2")
.exposedHeaders(LOCATION, AUTHORIZATION)
}
2. 문제 발생
코드를 바꿨더니 Preflight 요청 관련 오류가 발생했다.
Preflight란 CORS가 Simple Request가 아닐 때 하는 요청이다. Simple Request의 조건은 다양하지만, 일반적으로 Http Method가 GET
, POST
이면서 Content-Type
이 JSON이 아닐 때가 조건이다. 그렇기 때문에 일반적으로 application/json
을 사용하면 모두 preflight 요청을 보낸다.
그렇다면 origin을 열어줬는데 어디서 오류가 발생했을까?
오류를 확인해 보니 jwt가 존재하지 않기 때문에 발생했다. 왜 그런걸까?
public class AdminInterceptor implements HandlerInterceptor {
private AdminJwtService adminJwtService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
if (adminJwtService == null) {
adminJwtService = new AdminJwtService(new JwtService());
}
adminJwtService.validateAdminJWT();
return true;
}
}
Interceptor 코드는 다음과 같았다.
원인은 preflight 요청이 Authorization
Header를 포함한 요청이 아니고, Intercpetor는 preflight 요청이어도 동작을 하기 때문에 문제가 발생한 것이었다.
3. 해결
이를 해결하기 위해 다음과 같이 방어코드를 짜주었다.
if (CorsUtils.isPreFlightRequest()) {
return true
}
4. 결론
일단 오류는 해결했지만 위와 같이 해결하는 것은 Jwt관련 Interceptor가 추가될때 항상 방어코드를 짜줘야 한다는 단점이 있다. 이 코드를 어떻게 줄일 수 있을지 생각해봐야 겠다.
※ 참고
'개발 > [오류]' 카테고리의 다른 글
CORS와 스프링에서의 해결법 (0) | 2023.05.28 |
---|---|
Redirect URL에 쿼리 파라미터가 생기는 경우 (0) | 2022.04.14 |
Embedded Type Test 문제와 H2 GenerationType 문제 (0) | 2022.04.12 |
ModelAttribute 관련 오류 (0) | 2022.03.23 |
테스트 데이터 격리 (0) | 2022.03.18 |