CORS
CORS가 뭘까??
CORS란?
브라우저에서는 보안적인 이유로 cross-origin
HTTP 요청들을 제한합니다. 그래서 cross-origin
요청을 하려면 서버의 동의가 필요하다.
- 서버가 동의한다면 브라우저에서는 요청을 허락
- 동의하지 않는다면 브라우저에서 거절
이러한 허락을 구하고 거절하는 매커니즘을 HTTP-header를 이용해서 가능한데, 이를 CORS(Cross-Origin Resource Sharing)라고 부른다.
CORS를 번역하면 교차 출저 리소스 공유다. 출저는 오리진(Origin)의 번역 표현이다. URL에서 도메인만 뜻하는게 아니라 프로토콜과 포트까지 포함하는 개념이다.
브라우저에서 cross-origin
요청을 안전하게 할 수 있도록 하는 매커니즘이다.
- 도메인(Hostname):
myshop.com
- 출처(Origin):
https://www.myshop.com
cross-origin
이란 다음 중 한 가지라도 다른 경우를 말한다.
프로토콜
,도메인
,포트 번호
이 중 하나라도 다르면 CORS 에로를 만난다.
ex
URL | 접근이 가능한가? (SOP를 준수했는가?) |
---|---|
https://www.myshop.com/example/ | ✅ 프로토콜, 도메인, 포트가 같음 |
https://myshop.com/example2/ | ✅ 프로토콜, 도메인, 포트가 같음 |
http://myshop.com/example/ | ❌ 프로토콜과 포트가 다름 |
http://en.myshop.com/example/ | ❌ 도메인이 다름 |
http://www.myshop.com/example/ | ❌ 프로토콜이 다름 |
http://myshop.com:8080/example/ | ❌ 포트가 다름 |
- 출저: https://docs.tosspayments.com/resources/glossary/cors
CORS 필요한 이유
CORS가 없이 모든 곳에서 데이터를 요청할 수 있게 되면, 다른 사이트에서 원래 사이트를 흉내낼 수 있게 된다.
ex
기존 사이트와 완전히 동일하게 동작하도록 하여 사용자가 로그인을 하도록 만들고, 로그인했던 세션을 탈취하여 악의적으로 정보를 추출하거나 다른 사람의 정보를 입력하는 등 공격을 할 수 있다.
브라우저에서 보호하고, 필요한 경우에만 서버와 협의하여 요청할 수 있도록 하기 위해서 필요한다.
다른 출처 요청 정책
단순 요청(Simple Request)
- 서버로 요청을 한다.
- 서버의 응답이 왔을 때 브라우저가 요청한 Origin과 응답한 Access-Control-Request-Headers의 값을 비교하여 유요한 요청이라면 리소스를 응답합니다. (유효하지 않은면 에러가 발생한다.)
HTTP method가 다음 중 하나
GET
,HEAD
,POST
자동으로 설정되는 헤더는 제외하고, 설정할 수 있는 다음 CORS 안전 리스트 헤더들만 변경
Accept
,Accept-Language
,Content-Language
Content-Type이 다음과 같은 경우
application/x-www.form-urlencoded
,multipart/form-data
,text/plain
Simple requests라고 부른다. 이 요청은 추가적으로 확인하지 않고 바로 본 요청을 보낸다.
프리 플라이트(preflight Request)
- Origin 헤더에 현재 요청하는 origin과, Access-Control-Request-Method 헤더에 요청하는 HTTP method와 Access-Control-Request-Headers 요청 시 사용할 헤더를 OPTIONS 메서드로 서버로 요청한다. (내용물은 없이 헤더만 전송한다.)
- 브라우저가 서버에서 응답한 헤더를 보고 유효한 요청인지 확인합니다.
- 유효하지 않은 요청이라면 요청은 중단되고 에러가 발생합니다.
- 유효한 요청이라면 원래 요청으로 보내려던 요청을 다시 요청하여 리소스를 응답받습니다
Simple requests가 아닌 cross-origin 요청은 모두 preflight 요청을 하게된다. 하지만 실제 요청을 보내는 것이 안전한지 확인하기 위해 먼저 OPTIONS 메서드를 사용하여 cross-origin HTTP 요청을 보낸다.
사용자 데이터에 영향을 미칠 수 있는 요청이므로 사전에 확인 후 본 요청을 보낸다.
요청 헤더 목록
Origin
: 어디서 요청을 했는지 서버에 알려주는 주소Access-Control-Request-Method
: 요청을 할 때 실제 요청에서 어떤 메서드를 사용할 것인지 서버에게 알리기 위해 사용된다.Access-Control-Request-Headers
: 요청을 할 때 실제 요청에서 어떤 header를 사용할 것인지 서버에게 알리기 위해 사용된다.
응답 헤더 목록
Access-Control-Allow-Origin
: 브라우저가 해당 origin이 자원에 접근할 수 있도록 허용한다. 혹은*
이 credentials이 없는 요청에 한해서 모든 origin에서 접근이 가능하도록 허용한다.Access-Control-Expose-Headers
: 브라우저가 액세스할 수 있는 서버 화이트리스트 헤더를 허용한다.Access-Control-Max-Age
: 얼마나 오랫동안 요청이 캐싱 될 수 있는지를 나타낸다.Access-Control-Allow-Credentials
: Credentials가true
일 때 요청에 대한 응답이 노출될 수 있는지를 나타낸다.- 요청에 대한 응답의 일부로 사용되는 경우 실제 자격 증명을 사용하여 실제 요청을 수행할 수 있는지를 나타낸다.
Access-Control-Allow-Methods
: 요청에 대한 응답으로 허용되는 메서드를 나타낸다.Access-Control-Allow-Headers
: 요청에 대한 응답으로 실제 요청 시 사용할 수 있는 HTTP 헤더를 나타낸다.
신용 요청(Credentialed Request)
신용 요청은 쿠키, 인증 헤더, TLS 클라이언트 인증서 등의 신용정보와 함께 요청한다. 기본적으로, CORS 정책은 다른 출처 요청에 인증정보 포함을 허용하지 않는다. 요청에 인증을 포함하는 플래그가 있거나 access-control-allow-credentials가 true
로 설정한다면 요청할 수 있다.