딩관
오늘의 가치
딩관
전체 방문자
오늘
어제
  • 분류 전체보기 (176)
    • Kotlin (3)
      • 스프링 (2)
      • 기본문법 (1)
    • Python (75)
      • 기초문법 (43)
      • Python 모듈 (2)
      • Python 문제 (8)
      • Django (21)
      • DRF (1)
    • JavaScript (14)
      • JavaScript (4)
      • Typescript (0)
      • Node.js (4)
      • nest.js (2)
      • express (4)
    • SQL (12)
    • 기초CS (24)
      • 알고리즘 (16)
      • HTTP (4)
      • OperationSystem (2)
      • Linux (1)
    • 프로젝트 (8)
      • fake-trip (3)
      • 위코드 (5)
    • 잡동사니 (12)
    • Git (4)
      • git (1)
      • Git-hub (3)
    • 개발자 정진관 (12)
      • 개발자 이야기 (5)
      • 처음은 누구나 힘들다. (4)
      • 넌 이것도 이해 못하니? (3)
    • JAVA (5)
      • spring (2)
    • HTML & CSS (5)
    • Docker (1)
    • k8s (0)
      • k8s (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 위코드
  • Django
  • wecode
  • 파이썬
  • Node.js
  • http
  • Database
  • 개발자
  • JavaScript
  • TypeScript
  • MYSQL
  • python
  • SQL
  • Data Structure
  • 자바스크립트
  • 백엔드
  • java
  • 장고
  • 알고리즘
  • 자료구조

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
딩관

오늘의 가치

[Cors] Cors(Cross Origin Resource Sharing) 이란?!
잡동사니

[Cors] Cors(Cross Origin Resource Sharing) 이란?!

2022. 11. 21. 21:00

Cors(Cross Origin Resource Sharing) 

CORS는 교차 출처 요청을 허용하는 것이 안전한지 아닌지를 판별하기 위해 브라우저와 서버가 상호 통신하는 하나의 방법

저는 사실 이전까지 Cors는 교차출처자원을 금지하는 정책으로 알고있었지만 그것이 아닌

교차출처자원공유가 금지된 배경에서 공유를 가능하게 해주는 하나의 규약입니다.

이 배경이라함은 SOP입니다.

SOP(Same Origin Poricy)

SOP은 한 출처 에서 로드한 문서 또는 스크립트가 다른 출처의 리소스와 상호 작용할 수 있는 방법을 제한하는 중요한 보안 메커니즘입니다.

정책에 따라 웹브라우저 는 첫 번째 웹페이지에 포함된 스크립트가 두 번째 웹페이지의 데이터에 액세스하도록 허용하지만 두 웹페이지의 출처 가 동일한 경우에만 가능합니다

Origin 출처의 정의는?!

프로토콜 , 포트 (지정된 경우) 및 호스트 가 둘 다 동일한 경우 두 URL은 동일한 출처 를 가집니다. (MDN에서의 정의)

http://store.company.com/dir/page.html  을 기준으로 본다면

http://store.company.com/dir2/other.html O 경로만 다를 뿐
http://store.company.com/dir/inner/another.html O 경로만 다를 뿐
https://store.company.com/page.html X 다른 프로토콜
http://store.company.com:81/dir/page.html X 다른 포트( http://기본적으로 포트 80임)
http://news.company.com/dir/page.html X 다른 호스트

이렇게 됩니다.

Cors는 브라우저 구현스펙이다.

중요한 사실 한 가지는 이렇게 출처를 비교하는 로직이 서버에 구현된 스펙이 아니라 브라우저에 구현되어 있는 스펙이라는 것입니다.

Cors에러는 서버측에서 응답을 거부하는것이 아닌 브라우저가 응답을 분석해서 CORS 정책 위반이라고 판단되면 그 응답을 사용하지 않고 그냥 버리는 순서인 것 입니다.

(서버측에서 출처 분석후 거부하는 로직을 구현하는경우는 다른 이야기가 됩니다.)

즉, CORS는 브라우저의 구현 스펙에 포함되는 정책이기 때문에, 브라우저를 통하지 않고 서버 간 통신을 할 때는 이 정책이 적용되지 않습니다.

Cors의 동작방식

브라우저는 서버에 요청을 보낼때 해더에 Origin으로 본인의 출처를 기재하게 됩니다.

// 요청
Origin: https://evan-moon.github.io

이후 서버가 이 요청에 대한 응답 헤더의 Access-Control-Allow-Origin이라는 값에 “이 리소스를 접근하는 것이 허용된 출처”를 표기합니다.

// 응답
 Access-Control-Allow-Origin : https://evan-moon.github.io

이후 응답을 받은 브라우저는 자신이 보냈던 요청의 Origin과 서버가 보내준 응답의 Access-Control-Allow-Origin을 비교해본 후

이 응답이 유효한 응답인지 아닌지를 결정합니다.

이는 간단하게 설명한 방식이며 원래는 아래의 3가지 방식중 하나로 통신하게 됩니다.

  • preflight request
  • simple request
  • Credentialed request

Preflight request

방식은 일반적으로 우리가 웹 어플리케이션을 개발할 때 가장 마주치는 시나리오입니다.

  • 예비요청과 본요청으로 나누어 보냅니다
  • 이때 예비요청을 Preflight라고 합니다.
  • 예비요청시에는 OPTIONS메소드를 사용합니다.

예비요청은 해당 리소스를 얻을 수 있는지에 대한 확인절차이며 조건이 성립되지 않으면 본요청은 이루어지지 않습니다.

// 요청
OPTIONS https://evanmoon.tistory.com/rss

Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9,ko;q=0.8,ja;q=0.7,la;q=0.6
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: GET
Connection: keep-alive
Host: evanmoon.tistory.com
Origin: https://evan-moon.github.io
Referer: https://evan-moon.github.io/2020/05/21/about-cors/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: cross-site
// 응답
OPTIONS https://evanmoon.tistory.com/rss 200 OK

Access-Control-Allow-Origin: https://evanmoon.tistory.com
Content-Encoding: gzip
Content-Length: 699
Content-Type: text/xml; charset=utf-8
Date: Sun, 24 May 2020 11:52:33 GMT
P3P: CP='ALL DSP COR MON LAW OUR LEG DEL'
Server: Apache
Vary: Accept-Encoding
X-UA-Compatible: IE=Edge

Origin 이외에도 사용할 해더와 메소드역시 기재되어있습니다.

이때 중요한것은 예비 요청의 성공/실패 여부가 아니라 “응답 헤더에 유효한 Access-Control-Allow-Origin가 존재하는가"입니다.

Simple Request

예비요청 없이 본요청으로만 이루어진 간단한 요청입니다.

 

아무때나 할 수 있는것은 아니고 아래의 조건을 만족하여야 합니다.

  1. 요청의 메소드는 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만 허용된다.

Json데이터 타입이 허용안되며 Authorization또한 허용되지 않기에 생각보다 까다로운 조건입니다.

Credentialed Request

이 시나리오는 CORS의 기본적인 방식이라기 보다는 다른 출처 간 통신에서 좀 더 보안을 강화하고 싶을 때 사용하는 방법입니다.

기본 브라우저의 API는 별도의 옵션 없이 브라우저의 쿠키 정보나 인증과 관련된 헤더를 함부로 요청에 담지 않습니다.

브라우저 요청시 credential 옵션을 부여하여 추가적인 인증을 하는 방식이며 옵션의 종류는 아래와 같습니다.

same-origin (기본값) 같은 출처 간 요청에만 인증 정보를 담을 수 있다
include 모든 요청에 인증 정보를 담을 수 있다
omit 모든 요청에 인증 정보를 담지 않는다

다른 출처의 리소스를 요청할 때 단순히 Access-Control-Allow-Origin만 확인하는 것이 아니라 더 빡빡한 검사 조건을 추가합니다.

이 옵션을 사용하면 아래의 두가지 룰이 추가됩니다.

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

마지막으로

npm 의 cors()미들웨어의 기본값 코드를 보며 마치겠습니다.

예비요청에 대한 응답 스테이터스는 204네요

'잡동사니' 카테고리의 다른 글

[Pycharm]파이참 & 미니콘다 permission 오류 해결  (0) 2023.01.11
[JWT] JWT란?!  (0) 2022.11.24
[OOP]객체지향 프로그래밍이란?(OOP)  (0) 2022.11.20
[VScode] VScode 모듈 자동 import 상대경로로 변경하기  (0) 2022.10.22
[nest.js] nest에서 git 없이 프로젝트 생성하기  (0) 2022.10.19
    '잡동사니' 카테고리의 다른 글
    • [Pycharm]파이참 & 미니콘다 permission 오류 해결
    • [JWT] JWT란?!
    • [OOP]객체지향 프로그래밍이란?(OOP)
    • [VScode] VScode 모듈 자동 import 상대경로로 변경하기
    딩관
    딩관

    티스토리툴바