월하점
월하점의 개발 공부 일지
월하점
전체 방문자
오늘
어제
  • 분류 전체보기 (96)
    • Back-end (3)
    • PROJECT (1)
    • CS (15)
      • Operating System (0)
      • Network (4)
      • Data Structure (7)
      • Algorithm (0)
      • Database (4)
    • Problem Solving (52)
    • Programming Languages (1)
      • Javascript (0)
      • Python (1)
      • JAVA (0)
    • Codestates BEB 4기 (7)
    • Blockchain (12)
    • Linux (2)
    • Git (1)
    • 잡다한 (2)

공지사항

인기 글

태그

  • 프로그래머스
  • baekjoon
  • 자료구조
  • 네트워크
  • django
  • javascript
  • 알고리즘
  • Python
  • SWEA
  • node.js
  • CS

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
월하점

월하점의 개발 공부 일지

  • HOME
  • GUEST
  • WRITE
CORS(Cross-Origin Resource Sharing) 란? | cors가 필요한 이유, 동작 원리, preflight, 에러 해결법
CS/Network

CORS(Cross-Origin Resource Sharing) 란? | cors가 필요한 이유, 동작 원리, preflight, 에러 해결법

2022. 9. 7. 23:12

CORS(Cross-Origin Resource Sharing) 란?

  • 서로 다른 출처(origin)간에 리소스를 공유하는 것을 허용하는 정책
  • 기본적으로 차단되어 있다.
브라우저는 기본적으로 서로 다른 출처(origin)에 대해서 공유를 제한하는 SOP을 따른다.
SOP(Same-Origin Policy)이란 같은 출처끼리만 리소스를 공유할 수 있다는 정책이다.
    * HTML태그를 통한 이미지, CSS, Script 요청은 SOP에 의해 제한되지 않음
💡 origin: 출처를 의미하며, URL 구조에서 Protocol+Host+Port를 합친 것을 말함
   
    * port가 다를 경우 다른 출처로 인식
    * 80(HTTP), 443(HTTPS)번 포트는 생략 가능

 

 

 

 

CORS 가 정의된 이유

SOP(Same-Origin Policy)의 장점

 동일 출처 정책을 지키면 외부 리소스를 가져오지 못해 불편하지만, 동일 출처 정책은 XSS나 XSRF(=CSRF) 등의 보안 취약점을 노린 공격을 방어할 수 있다.

출처에 대한 비교는 브라우저에서 이루어지게 된다. 즉, 브라우저에서 SOP는 브라우저의 쿠키, 세션, 로컬스토리지 등에 사용자의 정보를 저장할 수 있기 때문에 다른 출처에 리소스를 공유하게 되면 보안상 취약해질 수 있다는 문제점 때문에 생긴 정책이다.

SOP(Same-Origin Policy)의 한계

 하지만 현실적으로는 외부 리소스를 참고하는 것은 필요하기 때문에 외부 리소스를 가져올 수 있는 방법이 존재해야 한다. 외부 리소스를 사용하기 위한 SOP의 예외 조항이 CORS이다.

 

 

 

 

CORS 의 동작 원리

 서버와 통신을 할 때 응답을 받는 브라우저에서 요청 헤더의 Origin필드와 응답 헤더의 Access-Control-Allow-Origin 필드를 비교하여 응답의 유효성을 판단한다.

 

 즉, 요청을 보내는 쪽에서 요청 헤더에 리소스를 필요로하는 URL을 Origin 필드에 담아서 보내고, 응답을 보내는 서버 쪽에선 Access-Contrl-Allow-Origin 필드에 리소스 접근이 허용된 출처를 담아서 보내 브라우저가 이를 비교하는 것이다.

 

 구체적인 요청 방법으로는 예비 요청을 보내는 preflight request, 예비 요청 없이 본 요청을 바로 보내는 simple request, 인증 정보를 담아서 보내는 credentialed request가 존재한다.

 

1. Simple request

단순 요청 방법은 서버에게 바로 요청을 보내는 방법

자바스크립트에서 API를 요청할 때 브라우저와 서버의 동작을 나타내는 그림

단순 요청은 서버에 API를 요청하고, 서버는 Access-Control-Allow-Origin 헤더를 포함한 응답을 브라우저에 보낸다. 브라우저는 Access-Control-Allow-Origin 헤더를 확인해서 CORS 동작을 수행할지 판단한다.

 

Simple request 조건

단순 요청으로 동작하기 위해서 서버로 전달하는 요청(request)이 만족해야 하는 조건 3가지

  1. 요청 메서드(method)는 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 중 하나를 사용해야 합니다.

⇒ 2: Authorization 헤더를 포함할 수 없고, 3: application/json 을 사용할 수 없어서 지키기 어렵 (많은 REST API가 Content type 으로 application/json 을 사용하기 때문)

 

 

2. Preflight request

서버에 예비 요청을 보내서 안전한지 판단한 후 본 요청을 보내는 방법

Preflight 요청 동작을 나타내는 그림

 

실제 리소스를 요청하기 전에 OPTIONS라는 메서드를 통해 실제 요청을 전송할지 판단한다.

OPTIONS 메서드로 서버에 예비 요청을 먼저 보내고, 서버는 이 예비 요청에 대한 응답으로 Access-Control-Allow-Origin 헤더를 포함한 응답을 브라우저에 보낸다. 브라우저는 단순 요청과 동일하게 Access-Control-Allow-Origin 헤더를 확인해서 CORS 동작을 수행할지 판단한다.

 

Preflight 를 날리는 이유는?

브라우저가 CORS를 지원하지 않은 서버에 도달하면 요청에 대한 응답을 보내지 않아 실제 요청이 수행되지 않도록 보호하기 위해서 만들어졌다.

예를 들어, POST 요청을 할 때, preflight가 없다면 브라우저가 CORS를 관리하기 때문에 CORS의 여부에 상관없이 이미 서버에서는 요청한 로직이 수행이 된 응답 값이 브라우저에 도달하게 된다. 하지만 CORS 에러로 인해서 브라우저는 그 사실을 알지 못하게 되고 치명적인 서버의 오류로 남아있을 수 있다. 따라서 이를 방지하고자 preflight request 를 보내는 것이다.

 

3. Credentialed Request

인증된 요청을 사용하는 방법

  • CORS의 기본적인 방식이라기 보단 다른 출처간 통신에서 좀 더 보안을 강화하고 싶을 때 사용하는 방법
  • 기본적으로 브라우저가 제공하는 비동기 리소스 요청 API인 XMLHttpRequest 객체나 fetch API는 별도의 옵션 없이 브라우저의 쿠키 정보나 인증과 관련된 헤더를 함부로 요청에 담지 않는다.
  • 이때 요청에 인증과 관련된 정보를 담을 수 있게 해주는 옵션이 바로 credentials 옵션이다.
    • same-origin (기본값) : 같은 출처 간 요청에만 인증 정보를 담는다.
    • include : 모든 요청에 인증 정보를 담는다.
    • omit : 모든 요청에 인증 정보를 담지 않는다.
  • credentials 옵션

same-origin이나 include와 같은 옵션을 사용하여 리소스 요청에 인증 정보가 포함된다면, 브라우저는 단순히 CORS 정책 위반 여부 검사(Access-Control-Allow-Origin) 확인과 더불어 추가 검사를 하게 된다.

  1. Access-Control-Allow-Origin에는 *를 사용할 수 없으며, 명시적인 URL이어야함
  2. 응답 헤더에는 반드시 Access-Control-Allow-Credentials: true가 존재해야함

 


[참고] 왜 Postman에서는 Cors가 발생되지 않을까?

 서버를 테스트하기 위해 Postman에서 요청을 실행할땐 문제없이 잘 동작하다가, 서버를 띄우고 브라우저에서 통신을 하는 순간 Cors 에러를 직면한 경험이 다들 있을 것이다.

 

 원인은 바로 "브라우저"에 있다.

 

💡 CORS 정책 위반 판단 검사를 시행하는 주체는 “브라우저” 이다.

💡 따라서, 브라우저 없이 서버 간 통신을 진행하는 Postman 에서는 Cors 에러를 볼 수 없는 것이다.


 

 

CORS 에러 해결 방법

서버에서 응답 헤더에 특정 헤더를 포함하는 방식으로 해결할 수 있다.

  • Access-Control-Allow-Origin: 특정 origin이 리소스에 접근이 가능하도록 허용합니다.
  • Access-Control-Allow-Method: 특정 HTTP Method만 리소스에 접근이 가능하도록 허용합니다.
  • Access-Control-Expose-Headers: 자바스크립트에서 헤더에 접근할 수 있도록 허용합니다.
  • credentials: 쿠키 등의 인증 정보를 전달할 수 있습니다.

 

 

 

정리

  • CORS란 서로 다른 Origin간에 자원을 공유하는 정책을 말하며 기본적으로 브라우저간에 차단되어있습니다.
  • Origin이란 출처를 말하며, Protocol + Host + Port 를 합친 것을 의미합니다.
  • CORS 에러는 서버에서 응답 헤더에 특정 헤더를 포함하는 방식으로 해결할 수 있습니다.
    • 예를 들어 Access-Control-Allow-Origin을 통해 특정 브라우저가 리소스에 접근이 가능하도록 허용할 수 있습니다.

 

 


참고 자료

  • https://beomy.github.io/tech/browser/cors/
  • https://velog.io/@wiostz98kr/CORS의-모든-것#3-credentialed-request
  • https://java-man.tistory.com/18
저작자표시 비영리 변경금지 (새창열림)

'CS > Network' 카테고리의 다른 글

DNS(Domain Name System)란? | DNS 정의, 구성 요소, 동작 과정  (0) 2022.09.10
SSL/TLS 란 무엇일까? | SSL/TLS 인증, SSL과 TLS의 차이점, TLS Handshake  (0) 2022.09.03
OSI 7 계층(Open Systems Interconnection 7 Layers)과 계층 별 역할 톺아보기 (+ TCP/IP계층, IP address VS. Mac address)  (0) 2022.08.31
    'CS/Network' 카테고리의 다른 글
    • DNS(Domain Name System)란? | DNS 정의, 구성 요소, 동작 과정
    • SSL/TLS 란 무엇일까? | SSL/TLS 인증, SSL과 TLS의 차이점, TLS Handshake
    • OSI 7 계층(Open Systems Interconnection 7 Layers)과 계층 별 역할 톺아보기 (+ TCP/IP계층, IP address VS. Mac address)
    월하점
    월하점
    개발 공부를 기록합니다. 웹을 위주로 공부하며 컴퓨터과학 이론도 함께 정리할 계획입니다.

    티스토리툴바