교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제입니다. 웹 애플리케이션은 리소스가 자신의 출처(도메인, 프로토콜, 포트)와 다를 때 교차 출처 HTTP 요청을 실행합니다.
쉽게 말해 브라우저에서는 보안적인 이유로 cross-origin HTTP 요청들을 제한한다. 그래서 cross-origin 요청을 하려면 해당 서버의 동의가 필요하다. 만약 서버가 동의한다면 브라우저에서는 요청을 허락하고, 동의하지 않는다면 브라우저에서 거절하게된다.
이러한 허락을 구하고 거절하는 메커니즘을 HTTP-header를 이용해서 가능한데, 이를 CORS라고 부른다.
다른 출처의 출처란 무엇인가에 대한 의문이 든다
다른 출처가 무엇인지 알기 위해서 먼저 URL의 구조를 보아야 함.
URL은 이러한 구조로 되어 있으며
출처(Origin)이란 URL 구조에서 프로토콜 + 호스트 주소 + 포트번호 를 합친 것을 말한다.
예를 들어서
http://nowon9159.tistory.com 이라는 URL과
http://nowon9159.tistory.com 이라는 URL은 같은 출처이며
http://nowon9159.tistory.com 이라는 URL과
https://nowon9159.tistory.com 이라는 URL은 다른 출처이다
왜? --> protocol이 다르기 때문에
이처럼
http://nowon9159.tistory.com 과
http://nowon9159.tistory.com:89
또는
http://nowon9159.naver.com 라는 URL은 각기 다른 출처이다
동일 출처 정책이란?
다른 서버에서 API를 호출할 때 잘 동작하다가 브라우저에서 API를 호출할 때 CORS Policy 오류가 발생하는 경우가 있다.
어떤 출처에서 불러운 문서나 스크립트가 다른 출처에서 가져온 리소스와 상호작용하는 것을 제한하며, 잠재적으로 해로울 수 있는 문서를 정책적으로 분리함으로 공격받을 수 있는 경로를 줄여준다.
동일 출처 정책을 지키면 외부 리소스를 가져오지 못해 불편하지만, XSS 나 XSRF 등의 보안 취약점을 노린 공격을 방어할 수 있다.
CORS 동작 방법
Simple requests와 preflight 요청이 있음
Simple requests
- HTTP mehod가 GET, HEAD, POST 다음 중 하나이고
- 자동으로 설정되는 헤더는 제외하고, 설정할 수 있는 다음 헤더들만 변경하면서 ( Accept, Accept-Language, Content-Language )
- Content-Type이 다음과 같은 경우
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
이 요청은 추가적으로 확인하지 않고 바로 본 요청을 보낸가
Preflight
- Origin헤더에 현재 요청하는 origin과, Access-Control-Requqst-Method헤더에 요청하는 HTTP method와 Access-Control-Request-Headers 요청 시 사용할 헤더를 OPTIONS 메서드 서버로 요청한다. 이때 내용물은 없이 헤더만 전송한다.
- 브라우저가 서버에서 응답한 헤더를 보고 유효한 요청인지 확인한다. 만약 유효하지 않은 요청이라면 요청을 중단되고 에러가 발생한다. 만약 유효한 요청이라면 원래 요청으로 보내려던 요청을 다시 요청하여 리소스를 응답 받는다.
Simple requests가 아닌 cross-origin 요청은 모두 preflight 요청을 하게 되는데, 실제 요청을 보내는 것이 안전한 지 확인하기 위해서 먼저 OPTIONS 메서드를 사용하여 cross-origin HTTP 요청을 보내게 된다. 이렇게 하는 이유는 사용자 데이터에 영향을 미칠 수 있는 요청이므로 사전에 확인 후 본 요청을 보낸다.
HTTP 요청 헤더 목록
헤더 이름 | 내용 |
Origin | Origin 헤더는 cross-site 접근 요청 또는 preflight request의 출처를 나타냅니다. |
Access-Control-Request-Method | Access-Control-Request-Method 헤더는 실제 요청에서 어떤 HTTP 메서드를 사용할지 서버에게 알려주기 위해, preflight request 할 때에 사용됩니다. |
Access-Control-Request-Headers | Access-Control-Request-Headers 헤더는 실제 요청에서 어떤 HTTP 헤더를 사용할지 서버에게 알려주기 위해, preflight request 할 때에 사용됩니다. |
HTTP 응답 헤더 목록
헤더 이름 | 내용 |
Origin | Origin 헤더는 cross-site 접근 요청 또는 preflight request의 출처를 나타냅니다. |
Access-Control-Request-Method | Access-Control-Request-Method 헤더는 실제 요청에서 어떤 HTTP 메서드를 사용할지 서버에게 알려주기 위해, preflight request 할 때에 사용됩니다. |
Access-Control-Request-Headers | Access-Control-Request-Headers 헤더는 실제 요청에서 어떤 HTTP 헤더를 사용할지 서버에게 알려주기 위해, preflight request 할 때에 사용됩니다. |
Access-Control-Allow-Origin | Access-Control-Allow-Origin 은 단일 출처를 지정하여 브라우저가 해당 출처가 리소스에 접근하도록 허용합니다. 또는 자격 증명이 없는 요청의 경우 "*" 와일드 카드는 브라우저의 origin에 상관없이 모든 리소스에 접근하도록 허용합니다. |
Access-Control-Expose-Headers | Access-Control-Expose-Headers 헤더를 사용하면 브라우저가 접근할 수 있는 헤더를 서버의 화이트리스트에 추가할 수 있습니다. |
Access-Control-Max-Age | Access-Control-Max-Age 헤더는 preflight request 요청 결과를 캐시할 수 있는 시간을 나타냅니다. |
Access-Control-Allow-Credentials | Access-Control-Allow-Credentials 헤더는 credentials 플래그가 true일 때 요청에 대한 응답을 표시할 수 있는지를 나타냅니다. preflight request에 대한 응답의 일부로 사용하는 경우, credentials을 사용하여 실제 요청을 수행할 수 있는지를 나타냅니다. simple GET requests는 preflighted되지 않으므로 credentials이 있는 리소스를 요청하면, 이 헤더가 리소스와 함께 반환되지 않습니다. 이 헤더가 없으면 브라우저에서 응답을 무시하고 웹 컨텐츠로 반환되지 않는다는 점을 주의하세요. |
Access-Control-Allow-Methods | Access-Control-Allow-Methods 헤더는 리소스에 접근할 때 허용되는 메서드를 지정합니다. 이 헤더는 preflight request에 대한 응답으로 사용됩니다. |
Access-Control-Allow-Headers | preflight request 에 대한 응답으로 Access-Control-Allow-Headers 헤더가 사용됩니다. 실제 요청시 사용할 수 있는 HTTP 헤더를 나타냅니다. |
[참조] :
https://developer.mozilla.org/ko/docs/Web/HTTP/CORS#access-control-expose-headers
https://developer.mozilla.org/ko/docs/Web/Security/Same-origin_policy
'CS 지식' 카테고리의 다른 글
미들웨어란? (0) | 2022.06.25 |
---|---|
API란? (0) | 2022.06.25 |
정적 분석과 동적 분석 (0) | 2022.06.18 |
Redis 란? (0) | 2022.06.13 |
컴파일러와 인터프리터란? (0) | 2022.05.25 |