2carrot84
by 2carrot84
3 min read

Categories

  • development

Tags

  • http
  • web

신규 입사한 회사 공통 라이브러리 소스를 보다 CorsRegistry를 통해서 CORS 설정하는 소스를 보고 CORS에 대해 자세히 모르는거 같아서 오전내내 읽어본 내용을 포스팅으로 옮겨 봅니다.

CORS (Cross-Origin Resource sharing)

추가 HTTP 헤더를 사용하여, 한 출처(도메인, 프로토콜, 포트)에서 실행 중인 웹 어플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제

A 도메인 script 등에서 B 도메인을 호출 시 B 도메인에서 이 접근을 허용할지 여부를 Access-Control-Allow-Origin 헤더에 다시 보낸다.

cross-site 방식으로 리소스 접근 허용 여부를 설정

HTTP 요청을 아래와 같이 2가지로 분류할 수 있다.

  1. simple requests
  2. preflighted requests

2가지에 대해 상세하게 알아보도록 하겠습니다.


simple requests (단순 요청)

CORS preflight를 트리거 하지 않는 요청을 묶어서 simple requests 라고 일컫으며, 아래 조건을 모두 충족하는 요청이 이에 해당한다.

  1. GET, POST, HEAD 메소드 중 하나의 메소드를 사용
  2. 유저 에이전트가 자동으로 설정한 헤더 외에 수동으로 설정할 수 있는 일부 헤더만 포함된 요청
    • 수동 설정 가능한 헤더 목록
      Accept
      Accept-Language
      Content-Language
      Content-Type
  3. Context-Type 헤더 값이 아래인 경우
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain
  4. 이벤트 리스너가 등록되지 않은 XMLHttpRequestUpload 객체를 사용한 요청
  5. ReadbleStreme 객체가 사용되지 않은 요청

preflighted request

OPTIONS 메소드를 통해 다른 도메인(다른 출처) 리소스로 HTTP 요청을 보내, 실제 요청(request)이 전송하기 안전한지 확인

cross-site(다른 도메인)간 통신을 위한 일종의 handshaking 정도라고 이해 하면 되지 않을까 싶습니다.

preflight request

첫 번째 통신은 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

Arun

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 에서 사용

마무리

지금 부터 업무간 맞이하는 개념이나 항목? 에 대해 깊이 있게 이해를 해보자는 취지로 오늘 포스팅을 작성해 보았지만 얼마나 지속할 수 있을지 스스로 의문을 품은채로..

그럼 이만. 🥕👋🏼🖐🏼

참고자료

https://developer.mozilla.org/ko/docs/Web/HTTP/CORS