* 해당 글은 공부 및 복습 목적으로 정리하기 위한 글 입니다.
CORS 란?
MDN Docs에서 CORS를 다음과 같이 정의하고 있습니다.
CORS는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제입니다. 웹 애플리케이션은 리소스가 자신의 출처(도메인, 프로토콜, 포트)와 다를 때 교차 출처 HTTP 요청을 실행합니다.
보안 상의 이유로 브라우저에서 웹 애플리케이션은 자신의 출처와 동일한 리소스만 불러올 수 있으며, 다른 출처의 소스를 불러오려면 그 출처에서 올바른 CORS 헤더를 포함한 응답을 반환해야 합니다.
CORS 예제를 통해 동작하는 방식을 살펴 본 뒤 Spring 서버 설정 방법까지 알아보도록 하겠습니다.
CORS 예제
CORS가 동작하는 방식은 세가지가 있습니다.
1. Simple requests (단순요청)
가장 간단한 접근 제어 프로토콜은 Origin 헤더와 Access-Control-Allow-Origin 을 사용하는 것입니다. Access-Control-Allow-Origin 헤더에는 요청의 Origin 헤더에서 전송된 값이 포함되어야 합니다.
원리는 간단하지만 단순요청에 조건이 많습니다. 아래의 조건을 만족해야 단순 요청으로 전달됩니다.
1. GET / HEAD / POST
2. 다음 헤더일 경우에만 적용된다.
- Accept
- Accept-Language
- Content-Language
- Content-Type (아래의 추가 요구 사항에 유의하세요.)
- DPR, Downlink, Save-Data, Viewport-Width, Width
3. Content-Type 허용 값
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
4. 요청에 사용된 XMLHttpRequestUpload 객체에는 이벤트 리스너가 등록되어 있지 않습니다.
5. 요청에 ReadableStream 객체가 사용되지 않습니다.
https://foo.example의 웹 컨텐츠가 https://bar.other 도메인의 컨텐츠를 호출합니다.
요청 헤더의 Origin을 통해 어디에서 요청이 왔는지 확인 할 수 있습니다.
서버는 이에 대한 응답으로 Access-Control-Allow-Origin 헤더를 전달하게 되는데 현재 Access-Control-Allow-Origin : *은 모든 도메인에서의 접근을 허용하는 것으로 https://foo.example의 요청만 허용하도록 하기 위해서는 Access-Control-Allow-Origin : https://foo.example 헤더를 전달하면 됩니다.
2. Preflighted requests (예비 요청)
먼저 다른 도메인의 리소스로 HTTP 요청을 보내 실제 요청이 전송하기에 안전한지 미리 확인합니다.
이때 예비 요청의 HTTP 메소드는 OPTIONS메소드를 사용합니다.
- 다른 도메인의 리소스 요청
- 브라우저는 OPTIONS의 독립적인 요청 메서드로 Origin 헤더에 자신의 출처를 보낸다
- 브라우저는 서버의 응답 헤더 정책(응답 헤더 중 Access-Control-Allow-Origin)과 비교하여 요청이 안전하다고 판단되면 본 요청을 보낸다.
- 서버가 본 요청에 대한 응답을 하면 요청을 시도한 웹 컨텐츠에 전달한다.
3. Requests with credentials (인증 요청)
인증된 요청은 클라이언트가 자격 인증 정보(Credential)를 실어 요청하는 방법이다. 자격 인증 정보에는 쿠키, Authorization 헤더에서 설정하는 토큰 값 등이 있다.
1) 클라이언트 설정
클라이언트에서 인증 정보를 보내도록 하기 위해 credentials 옵션을 설정한다.
- same-origin (default) : 같은 출처 간 요청에만 인증 정보를 담는다.
- include : 모든 요청에 인증 정보를 담는다.
- omit : 모든 요청에 인증 정보를 담지 않는다.
fetch('https://example.com', {
credentials: 'include',
});
// fetch 공식문서 : https://developer.mozilla.org/ko/docs/Web/API/Fetch_API/Using_Fetch
2. 서버 헤더 설정
서버에서는 일반적인 요청과 다르게 다음 조건을 만족하는 헤더로 응답해주어야 한다.
- Access-Control-Allow-Credentials : true
- Access-Control-Allow-Origin, Methods, Headers : *(와일드카드 문자) 사용 불가
Spring 전역 설정
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:8080")
.allowedMethods("POST")
.allowCredentials(true)
.maxAge(6000)
}
}
Spring 특정 컨트롤러 설정
@Controller
@CrossOrigin(origins = "*", methods = RequestMethod.GET)
public class testController {
@GetMapping("/url")
@CrossOrigin(origins = "*", methods = RequestMethod.GET)
@ResponseBody
public List<Object> findAll(){
return service.findAll();
}
}
참고자료
- https://developer.mozilla.org/ko/docs/Web/HTTP/CORS
- https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-CORS-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95-%F0%9F%91%8F
도움을 주신 분들 감사합니다.
'서버 > 네트워크 및 인프라' 카테고리의 다른 글
Jenkins에서 Gradle Build시 '허가 거부' 해결한 경험 (0) | 2024.07.06 |
---|---|
[Kafka] Consumer Group 삭제하기 (0) | 2024.05.07 |
[Oracle Cloud] DB 데이터가 초기화 될 경우 (0) | 2022.11.21 |
[Linux] Zshell, oh-my-zsh 설치하기 (0) | 2022.11.13 |
세션 클러스터링이란? (0) | 2021.11.10 |
댓글