티스토리 뷰

Javascript

CORS란?

서스포PAR 2022. 3. 1. 18:05

 

 

API를 하다 보면 cors오류를 접하게 되었다.

왜 발생하는지 어떻게 해결하는지 알아보자!

 

 


 

💖 CORS(Cross-Origin Resource Sharing)


🚨 Access to fetch at ‘https://api.lubycon.com/me’ from origin ‘http://localhost:3000’ has been blocked by CORS policy: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.


브라우저에서 cross-origin 요청을 안전하게 할 수 있도록 하는 메커니즘입니다.

 

-  웹 애플리케이션은 리소스가 자신의 출처(도메인, 프로토콜, 포트)와 다를 때 교차 출처 HTTP 요청을 실행한다.

 

-  브라우저는 보안 상의 이유로, 스크립트에서 시작한 교차 출처 HTTP 요청을 제한한다.

 

- cross-origin 요청을 하려면 서버의 동의가 필요합니다. 만약 서버가 동의한다면 브라우저에서는 요청을 허락하고, 동의하지 않는다면 브라우저에서 거절합니다. 허락을 구하고 거절하는 메커니즘을 HTTP-header를 이용해서 가능한데, 이를 CORS(Cross-Origin Resource Sharing)라고 부릅니다.

 

 

 

 

💻  동일 출처 정책 - SOP(Same-Origin Policy)?

더보기

동일 출처 정책(same-origin policy)은 어떤 출처에서 불러온 문서나 스크립트가 다른 출처에서 가져온 리소스와 상호작용하는 것을 제한하는 중요한 보안 방식입니다. 동일 출처 정책은 잠재적으로 해로울 수 있는 문서를 분리해, 공격받을 수 있는 경로를 줄입니다.

 

즉, 동일 출처 정책은 웹 브라우저 보안을 위해 프로토콜, 호스트, 포트가 동일한 서버로만 ajax 요청을 주고 받을 수 있도록 한 정책이다.

 

 

👉 동일 출처 원칙 사용 이유

1. XSS 와 같은 스크립트 삽입 공격을 통해서 출처가 다른 웹 어플리케이션에 접근을 방지합니다


2. 현대의 웹 어플리케이션은 인가된(authenticated) 사용자의 세션을 유지하기 위해서 HTTP Cookie 에 의존하기 때문입니다.


3. 최근 웹 어플리케이션 들은 인증된 사용자 세션정보를 HTTP 쿠키에 담아서 광범위하게 사용하곤 하는데, 출처가 다른 페이지에서 스크립트를 이용해 해당 쿠키정보를 추출할 수 있기 때문입니다.


4. 데이터의 기밀성 또는 일관성을 유지하기 위해서 클라이언트 측에서 관계 없는 사이트에서 제공된 컨탠츠를 분리 해야합니다.

 

 

💻 출처(Origin)?

더보기

서버의 위치를 의미하는 https://google.com과 같은 URL들은 마치 하나의 문자열 같아 보여도, 사실은 여러 개의 구성 요소로 이루어져있다.

 

 

 

 

이때 출처는 Protocol과 Host, 그리고 위 그림에는 나와있지 않지만 :80, :443과 같은 포트 번호까지 모두 합친 것을 의미한다. 즉, 서버의 위치를 찾아가기 위해 필요한 가장 기본적인 것들을 합쳐놓은 것이다.

 

또한 출처 내의 포트 번호는 생략이 가능한데, 이는 각 웹에서 사용하는 HTTP, HTTPS 프로토콜의 기본 포트 번호가 정해져있기 때문이다. HTTP가 정의된 RFC 2616 문서를 보면 다음과 같이 기본 포트 번호가 함께 정의되어있는 것을 볼 수 있다.

 

그러나 만약 https://google.com:443과 같이 출처에 포트 번호가 명시적으로 포함되어 있다면 이 포트 번호까지 모두 일치해야 같은 출처라고 인정된다. 하지만 이 케이스에 대한 명확한 정의가 표준으로 정해진 것은 아니기 때문에, 더 정확히 이야기하자면 어떤 경우에는 같은 출처, 또 어떤 경우에는 다른 출처로 판단될 수도 있다. (진리의 케바케)

 

 

 

EX ) https://www.google.com과 출처 비교 

 URI 를 결정하는 알고리즘은 RFC 6454 에 명시되어 있음

 

비교 대상 URL 결과 이유
https://www.google.com/main 성공 같은 호스트, 포트, 프로토콜
https://www.google.com:81 실패 다른 포트
http://www.google.com 실패 다른 프로토콜
https://mail.google.com 실패 다른 호스트 (정확한 일치 필요)
https://www.google.com:80 의존 명시적 포트 (브라우저 구현에 따라 다름)

 

 

 

 

👏 cross-origin

cross-origin이란 다음 중 한 가지라도 다른 경우를 말합니다.

 

1. 프로토콜 - http와 https는 프로토콜이 다르다.

2. 도메인 - domain.com과 other-domain.com은 다르다.

3. 포트 번호 - 8080포트와 3000포트는 다르다.

 

 

 

 


 

 

🎠 CORS가 존재하는 이유

CORS가 없이 모든 곳에서 데이터를 요청할 수 있게 되면, 다른 사이트에서 원래 사이트를 흉내낼 수 있게 됩니다.

 

예를 들어서 기존 사이트와 완전히 동일하게 동작하도록 하여 사용자가 로그인을 하도록 만들고, 로그인했던 세션을 탈취하여 악의적으로 정보를 추출하거나 다른 사람의 정보를 입력하는 등 공격을 할 수 있습니다.

 

이렇나 공격을 할 수 없도록 브라우저에서 보호하고, 필요한 경우 에만 서버와 협의하여 요청할 수 있도록 하기 위해서 필요합니다.

 

 

 

 


 

 

📑 CORS 동작

1. 기본적으로 웹은 다른 출처의 리소스를 요청할 때는 HTTP 프로토콜을 사용하여 요청을 하는데,
이때 브라우저는 요청 헤더 (request header)에 Origin 필드에 요청을 보내는 출처를 담아 전송한다.

 

2. 서버는 요청에 대한 응답을 하는데, 응답 헤더 (response header)에 Access-Control-Allow-Origin이라는 값에 '이 리소스를 접근하는 것이 허용된 출처'를 내려준다.


3. 이후 응답을 받은 브라우저는 자신이 보냈던 요청의 Origin과 서버가 보내준 응답의 Access-Control-Allow-Origin비교해 본 후 이 응답이 유효한 응답인지 아닌지를 결정한다.

 

👉🏻 이것이 기본적인 CORS 동작의 흐름이다. 하지만 모든 CORS 동작의 방식은 아니다.

 

 

 

 

 


 

 

🎠 CORS 동작 시나리오

🔊 Prefilght Request

1. Preflight 방식은, 요청을 한번에 보내는 것이 아니라 예비 요청과 본 요청으로 나누어서 서버로 전송한다.

 

2. 본 요청을 보내기 전 미리 예비로 보내는 요청을 Preflight라고 하며, HTTP 메서드 중 하나인 OPTIONS 메서드를 사용한다.

👉🏻  WHY?
예비 요청을 함으로써 본 요청을 보내기 전 브라우저 스스로가 요청을 보내는 것에 대한 안전성을 확인함에 있다.
서버는 이 예비 요청에 대한 응답으로 현재 자신이 어떤 것들을 허용 하고, 어떤 것들을 금지하고 있는지에 대한 정보를 응답 헤더에 담아서 브라우저에게 다시 보내준다.

 

단순히 Origin에 대한 정보 뿐만 아니라 자신이 예비 요청 이후에 보낼 본 요청에 대한 다른 정보들도 함께 전송 한다. 어떤 헤더를 포함 할 것인지, 어떤 HTTP 메서드를 사용하여 요청을 보낼 것인지 말이다.

 

 

 

 


 

 

🔊 Simple Request

Preflight 요청과는 달리, 예비 요청을 보내지 않고, 서버에게 바로 본 요청을 전송한다.
이 후 서버가 응답 헤더에 Access-Control-Allow-Origin과 같은 값을 보내주면 그때 브라우저가 CORS 정책 위반 여부를 검사하는 방식이다.

 

👉🏻 동작 조건

1. 요청의 메소드는 GETHEADPOST 중 하나여야 한다.

- 1번 조건의 경우 그리 까다롭지는 않다.

 

2. AcceptAccept-LanguageContent-LanguageContent-TypeDPRDownlinkSave-DataViewport-WidthWidth 외의 다른 헤더를 사용하면 안된다.

- 2번의 명시된 헤더들은 정말 기본적인 헤더들이다. 복잡하고 상용화된 웹 어플리케이션에서는 이 헤더들 외에 추가적인 헤더를 사용하지 않는 경우는 찾기 힘들다. 인증 동작을 위한 Authoriztion 헤더만 하더라도 저 조건을 지킬 수 없다.

 

3. 만약 Content-Type를 사용하는 경우에는 application/x-www-form-urlencodedmultipart/form-datatext/plain만 허용된다.

- 오늘 날의 REST 혹은 HTTP API들은 text/xml이나 application/json 컨텐츠 타입을 가지도록 설계 되기 때문에 사실 상 조건을 충족시키기란 쉽지 않다.

 

 

 

 


 

🔊 Credentialed Request.

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

 

다른 출처 간 통신의 좀 더 보안을 강화하고자 할 때 사용한다. 브라우저가 제공하는 비동기 리소스 요청 API인 XMLHttpRequest 객체나 fetch API는 별도의 옵션 없이 브라우저의 쿠키 정보나 인증과 관련된 헤더를 함부로 요청에 담지 않는다. 이때 요청에 인증과 관련된 정보를 담을 수 있게 해주는 옵션이 바로 credentials 옵션이다.

 

credentials도 세가지 옵션을 가지고 있다.

 

1. same-origin : 같은 출처 간 요청에만 인증 정보를 담을 수 있다.

2. include : 모든 요청에 인증 정보를 담을 수 있다.

3. omit - : 모든 요청에 인증 정보를 담지 않는다.

 

👉🏻 다른 출처 사이트로의 요청에 쿠키와 같은 인증정보를 포함시키고자 한다면 ?
→  credentials: 'include' 옵션을 추가

 

👉🏻 동작 조건

1. Access-Control-Allow-Origin: * 이면 안되며, 명시적인 URL을 설정하여햐 한다.
ex) Access-Control-Allow-Origin: https://xxx.com

 

2. 응답 헤더에는 반드시 Access-Control-Allow-Credentials: true가 존재해야한다.

 

 

 

 


 

📑 요청 헤더 목록

 

1. Origin

 

2. Access-Control-Request-Method

- preflight 요청을 할 때 실제 요청에서 어떤 메서드를 사용할 것인지 서버에게 알리기 위해 사용됩니다.

 

3. Access-Control-Request-Headers

- preflight요청을 할 때 실제 요청에서 어떤 header를 사용할 것인지 서버에게 알리기 위해 사용됩니다.

 

 

 

📑 응답 헤더 목록

1. Access-Control-Allow-Origin

- 브라우저가 해당 origin이 자원에 접근할 수 있도록 허용합니다. 혹은 *은 credentials이 없는 요청에 한해서 모든 origin에서 접근이 가능하도록 허용합니다.

 

2. Access-Control-Expose-Headers

- 브라우저가 액세스할 수 있는 서버 화이트리스트 헤더를 허용합니다.

 

3. Access-Control-Max-Age

- 얼마나 오랫동안 preflight요청이 캐싱 될 수 있는지를 나타낸다.

 

4. Access-Control-Allow-Credentials

- Credentials가 true 일 때 요청에 대한 응답이 노출될 수 있는지를 나타냅니다.

- preflight요청에 대한 응답의 일부로 사용되는 경우 실제 자격 증명을 사용하여 실제 요청을 수행할 수 있는지를 나타냅니다.

- 간단한 GET 요청은 preflight되지 않으므로 자격 증명이 있는 리소스를 요청하면 헤더가 리소스와 함께 반환되지 않으면 브라우저에서 응답을 무시하고 웹 콘텐츠로 반환하지 않습니다.

 

5. Access-Control-Allow-Methods

- preflight`요청에 대한 대한 응답으로 허용되는 메서드들을 나타냅니다.

 

6. Access-Control-Allow-Headers

- preflight요청에 대한 대한 응답으로 실제 요청 시 사용할 수 있는 HTTP 헤더를 나타냅니다.

 

 

 

 

 

 


 

 

https://tlsdnjs12.tistory.com/25

 

API란?

API를 사용하는데 이것이 어떤 내용인지 처음엔 자세히 몰랐다. 하지만 알아야겠다는 마음을 먹고 기본 개념부터 정리하자고 마음먹었다 🎁 기본이론부터 호출방법까지 차차 알아보도록 하자

tlsdnjs12.tistory.com

 

https://tlsdnjs12.tistory.com/26

 

fetch와 axios 차이점과 비교

저번에 API에 대해서 알아봤습니다. 자바스크립트에서 HTTP Requests를 위한 방법이 두가지가 존재하는데 🎁  오늘은 어떤것이 존재하고 어떤 차이점이 존재하는지 알아보겠습니다. 🎁 💖 Fetch ES6

tlsdnjs12.tistory.com

 

'Javascript' 카테고리의 다른 글

[Javascript] Spread/ Reat문법 (feat. 비구조화(구조분해) 할당)  (0) 2022.04.25
정규 표현식(regular expression) 이란?  (0) 2022.03.21
fetch와 axios 차이점과 비교  (0) 2022.02.28
API란?  (0) 2022.02.22
localstorage 이란?  (0) 2022.01.10
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함