클라이언트 작업을 했을 때 가장 먼저 겪은 에러는 CORS 에러였습니다. 제 머리속에 강하게 박혀 대체 이 CORS가 뭔지에 대해 알아보려 합니다.
CORS란?
교차 출처 리소스 공유(Cross-origin resource sharing, CORS), 교차 출처 자원 공유는 웹 페이지 상의 제한된 리소스를 최초 자원이 서비스된 도메인 밖의 다른 도메인으로부터 요청할 수 있게 허용하는 구조이다.
origin = protocol + host + port를 말합니다. origin을 집 주소라고 생각하면 편한데요. 다시 말해 다른 집에서 들어오는 접근을 허용하는 정책입니다.
원래는 SOP 정책이다
다른 집에서 함부로 우리 집의 리소스를 공유하면 당연히 문제가 되겠죠? 그래서 브라우저는 SOP(Same-Origin-Policy)정책을 따릅니다. 하지만 점차 다른 출처간에 통신이 필요해져 CORS 정책을 새롭게 만듭니다.
어떤 흐름인가?
단순하다. Browser가 서버가 준 응답을 확인하여 허용된 오리진인지 검증하여 처리한다.
그래도 보안문제가 있지 않은지?
그렇다. 이를 위해 동작방식 3가지를 정했다.
Springboot에서 다음과 같이 설정합니다.
@Slf4j
@RestController
@CrossOrigin(origins = "http://localhost:3000", exposedHeaders = "Authorization")
public class WriteController {
@GetMapping("/write")
public Map<String, String> write() {
Map<String, String> hashMap = new HashMap<>();
hashMap.put("message", "글쓰기");
log.info("작업중");
return hashMap;
}
}
@CrossOrigin 설정
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
return
httpSecurity
.cors(cors -> cors.configurationSource(request -> {
var corsConfiguration = new CorsConfiguration();
if (request.getRequestURI().startsWith("/write")) {
corsConfiguration.setAllowedOrigins(List.of("http://localhost:3000"));
corsConfiguration.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE", "OPTIONS"));
corsConfiguration.setAllowedHeaders(List.of("*"));
}
return corsConfiguration;
}))
...
cors 설정을 처음 해보면 .cors(Customizer.withDefaults()) 설정을 할 수 있는데 이는 모든 api에 대해 cors를 허용하는 것이므로 관리가 힘듭니다.
따라서 위의 코드처럼 cors 허용을 원하는 api에 대해 조건을 걸어줍니다. method도 확장할 수 있습니다.
추가로 security에 cors 설정을 해주기만 하면 @CrossOrigin 설정이 적용이 되어서 위의 조건문에 해당하는 api가 아니더라고 @CrossOrigin이 설정된 api도 작동이 되는 것을 확인했습니다. 뭔가 설정이 중구난방이 되는 것 같아 마음에 들진 않았는데 Security에 모든 설정을 할 지, Controller에 설정을 추가로 할 지는 개인 취향인 것 같습니다.
읽어주셔서 감사하고 잘못된 점은 언제든지 태클 걸어주세요.