신규 입사한 회사 공통 라이브러리 소스를 보다 CorsRegistry를 통해서 CORS 설정하는 소스를 보고 CORS에 대해 자세히 모르는거 같아서 오전내내 읽어본 내용을 포스팅으로 옮겨 봅니다.
CORS (Cross-Origin Resource sharing)
추가 HTTP 헤더를 사용하여, 한
출처(도메인, 프로토콜, 포트)
에서 실행 중인 웹 어플리케이션이다른 출처의 선택한 자원에 접근
할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제
A 도메인 script 등에서 B 도메인을 호출 시 B 도메인에서 이 접근을 허용할지 여부를 Access-Control-Allow-Origin
헤더에 다시 보낸다.
cross-site 방식으로 리소스 접근 허용 여부를 설정
HTTP 요청을 아래와 같이 2가지로 분류할 수 있다.
- simple requests
- preflighted requests
2가지에 대해 상세하게 알아보도록 하겠습니다.
simple requests (단순 요청)
CORS preflight를 트리거 하지 않는 요청을 묶어서 simple requests 라고 일컫으며, 아래 조건을 모두 충족하는 요청이 이에 해당한다.
- GET, POST, HEAD 메소드 중 하나의 메소드를 사용
- 유저 에이전트가 자동으로 설정한 헤더 외에 수동으로 설정할 수 있는 일부 헤더만 포함된 요청
- 수동 설정 가능한 헤더 목록
Accept
Accept-Language
Content-Language
Content-Type- Context-Type 헤더 값이 아래인 경우
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
- 이벤트 리스너가 등록되지 않은 XMLHttpRequestUpload 객체를 사용한 요청
- 이들은 XMLHttpRequest.upload 프러퍼티를 사용하여 접근 - 무슨 말인지..🤬
- ReadbleStreme 객체가 사용되지 않은 요청
preflighted request
OPTIONS 메소드
를 통해 다른 도메인(다른 출처) 리소스로 HTTP 요청을 보내, 실제 요청(request)이 전송하기 안전한지 확인
cross-site(다른 도메인)간 통신을 위한 일종의 handshaking 정도라고 이해 하면 되지 않을까 싶습니다.
첫 번째 통신은 preflight request/response입니다.
OPTIONS /resources/post-here/ HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Connection: keep-alive Origin: http://foo.example Access-Control-Request-Method: POST Access-Control-Request-Headers: X-PINGOTHER, Content-Type
HTTP/1.1 204 No Content Date: Mon, 01 Dec 2008 01:15:39 GMT Server: Apache/2 Access-Control-Allow-Origin: https://foo.example Access-Control-Allow-Methods: POST, GET, OPTIONS Access-Control-Allow-Headers: X-PINGOTHER, Content-Type Access-Control-Max-Age: 86400 Vary: Accept-Encoding, Origin Keep-Alive: timeout=2, max=100 Connection: Keep-Alive
preflight request가 완료되면 실제 요청을 전송합니다.
POST /resources/post-here/ HTTP/1.1 Host: bar.other User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,/;q=0.8 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,decflate Connection: keep-alive X-PINGOTHER: pingpong Content-Type: text/xml; charset=UTF-8 Referer: https://foo.example/examples/preflightInvocation.html Content-Length: 55 Origin: https://foo.example Pragma: no-cache Cache-Control: no-cache
HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:40 GMT Server: Apache/2 Access-Control-Allow-Origin: https://foo.example Vary: Accept-Encoding, Origin Content-Encoding: gzip Content-Length: 235 Keep-Alive: timeout=2, max=99 Connection: Keep-Alive Content-Type: text/plain
[Some GZIP’d payload]
실제 Request 에서 보낼 항목을 Access-Control-Request-* 헤더에 포함
하여 전송하며, 실제 Request 에선 Access-Control-Request-* 헤더
는 포함하지 않고 전송한다.
인증정보를 포함한 요청
credentialed request 는 HTTP Cookie 와 HTTP Authentication 정보(= 인증정보)를 인식한다.
기본적으로 cross-site XMLHttpRequest 나 Fetch 호출에서 브라우저는 자격 증명(= 인증정보)을 보내지 않습니다. XMLHttpRequest 객체나 Request 생성자가 호출될 때 특정 플래그(withCredentials)를 설정해야 합니다.
simple GET request 는 preflighted 되지 않기 때문에 일반적인 cross-site 요청시 인증정보가 포함되는 경우 Access-Control-Allow-Credentials: true 헤더가 없는 응답에 포함되지 않는 경우 브라우저에서 정상적으로 웹 컨텐츠 응답 제공하지 않는다.
CORS 요청의 경우, 브라우저가 프런트엔드 JavaScript 코드에 대한 응답을 노출하기 위해서는 서버(Access-Control-Allow-Credentials 헤더 사용)와 클라이언트(XHR, Fetch 또는 Ajax 요청에 대한 자격 증명 모드를 설정하여)가 자격 증명 포함을 선택하고 있음을 표시해야 합니다.
HTTP 응답 헤더
Access-Control-Allow-Origin
단일 출처를 지정하여 브라우저가 해당 출처가 리소스에 접근하는 것을 허용함
자격 증명이 없는 요청의 경우 와일드 카드(*)는 브라우저 origin 에 상관없이 모든 리소스에 접근을 허용함
즉, 서버 입장에서 접근을 허용할 cross-site 를 설정하는 용도
Access-Control-Expose-Headers
브라우저에서 접근할 수 있는 헤더를 서버의 화이트 리스트에 추가
Access-Control-Max-Age
preflight request 캐싱 주기(단위 : 초) 해당 헤더값 만큼 새로운 preflight request 를 보내지 않고, 기존에 받은 응답값을 사용
Access-Control-Allow-Credentials - 가장 이해 하기 어려운 항목..😅
헤더는 credentials 플래그가 true 일때, 요청에 대한 응답을 표시활 수 있는지 나타냄
preflight request 에 대한 응답의 일부로 사용하는 경우, credentials 를 사용하여 실제 요청을 수행할 수 있는지 나타냄
simple get request(단순 요청) 는 preflighted 되지 않음으로,credentials 가 있는 리소스를 요청하면 이 헤더가 리소스를 반환하지 않는다.
Access-Control-Allow-Methods
리소스에 접근할때 허용되는 메소드를 지정
Access-Control-Allow-Headers
preflight request 에 대한 응답으로 해당 헤더 사용 실제 요청시 사용할 수 있는 헤더들을 나태냄
HTTP 요청 헤더
Cross-Origin 리소스 공유 명세에 정의된 대로 서버가 접근 제어 요청을 위해 보내는 HTTP 응답 헤더가 나열
Origin : cross-site 접근 요청 or preflight request 출처
요청이 시작된 서버를 나타내는
URI
(상세 path 는 제외됨)
Access-Control-Request-Method
실제 요청시 어떤 HTTP 메소드를 사용할지 서버에게 알려주기 위해 preflight request 에서 사용
Access-Control-Request-Headers
실제 요청시 어떤 HTTP 헤더를 사용할지 서버에게 알려주기 위해 preflight request 에서 사용
마무리
지금 부터 업무간 맞이하는 개념이나 항목? 에 대해 깊이 있게 이해를 해보자는 취지로 오늘 포스팅을 작성해 보았지만 얼마나 지속할 수 있을지 스스로 의문을 품은채로..
그럼 이만. 🥕👋🏼🖐🏼