관리 메뉴

Rootable의 개발일기

CORS(Cross-Origin Resource Sharing) Policy 본문

Network

CORS(Cross-Origin Resource Sharing) Policy

dev-rootable 2024. 1. 16. 21:21

JSON 통신을 하는 프로젝트를 진행하면 다음과 같은 에러를 만날 수 있다.

 

CORS 에러 메시지

 

그래서 해당 글에서는 CORS 정책과 관련된 내용을 정리해 보려고 한다.

 

📌 CORS란?

 

다른 출처 간의 자원을 공유하는 정책

 

🔍 출처(Origin)

 

우리가 어떤 사이트에 접근할 때 작성하는 URL은 아래와 같이 구성되어 있다.

 

URL 구성

 

여기서 Protocol, Host, Port를 합친 URL을 출처(Origin)이라고 한다.

 

📌 웹 보안 정책

 

웹은 보안을 위해 콘텐츠 보안, 연결 보안, 데이터 보안, 정보 유출, 무결성, 클릭재킹 보호, 사용자 정보 보안 등의 주제로 나눠 각 주제에 대한 보안 솔루션을 갖고 있다. 이 중에서 무결성을 위해 출처에 대한 정책을 갖고 있는데 이것에 대해 이야기하려고 한다.

 

🔍 Same Origin Policy(SOP, 동일 출처 정책)

 

A 라는 출처에서 로드한 문서나 script가 B라는 출처의 리소스와 상호 작용할 수 있는 방식을 제한하는 중요한 보안 메커니즘을 말한다.

 

즉, 동일 출처 서버에 있는 리소스는 자유롭게 가져올 수 있지만, 다른 출처 서버에 있는 리소스는 상호작용이 불가능하다는 말이다.

 

이 정책을 따르지 않는다는 것은 출처가 다른 외부의 요청을 받아들이는 것이므로 보안상 매우 취약한 상태라고 할 수 있다. 가령, CSRF(Cross-Site Request Forgery) 나 XSS(Cross-Site Scripting)와 같은 공격의 전제 조건은 외부의 요청을 받아들이는 것에서 시작한다.

 

✔ SOP 정책을 따르는 리소스

 

XMLHttpRequest
Fetch API 스크립트
외부로부터 ajax 요청

 

🚖 출처 비교와 차단은 브라우저가 수행

== 서버 간 통신은 SOP로부터 자유롭다.
== Proxy 서버를 통해 우회하는 방법도 있다.

 

🔍 Cross-Origin Resource Sharing Policy (CORS, 교차 출처 리소스 공유)

 

최근에는 다른 출처에 있는 리소스를 가져와서 사용하는 일이 매우 흔하므로 SOP의 예외 조항인 CORS 정책을 두게 되었다.

 

✔ CORS 정책을 따르는 리소스

 

<img>, <video>, <audio>, <embed>, <object>
<link> 태그로 다른 도메인의 CSS 가져오기
<script> 태그로 다른 도메인의 JS 가져오기 (특정 API는 차단될 수 있음)
<iframe>으로 삽입되는 모든 것

 

📌 CORS 작동 방식

 

🔍 예비 요청 (Preflight Request)

 

브라우저는 서버와 잘 통신되는지 확인하기 위해 본 요청에 앞서 예비 요청을 보낸다. 이것은 본 요청을 보내기 전에 브라우저 스스로 안전한 요청인지 미리 확인하는 절차이다.

 

이처럼 브라우저가 예비 요청을 보내는 것을 Preflight라고 부르며, 해당 요청은 OPTIONS라는 HTTP 메서드를 사용한다.

 

fetch() 요청 과정

 

요청 필드 의미

<Browser>
Origin: 자신의 출처
Access-Control-Request-Methods: 실제 요청에 사용할 메서드
Access-Control-Request-Headers: 실제 요청에 사용할 헤더들

<Server>
Access-Control-Allow-Origin: 허용되는 Origin 목록
Access-Control-Allow-Methods: 허용되는 메서드 목록
Access-Control-Allow-Headers: 허용되는 헤더들의 목록
Access-Control-Max-Age: 해당 예비 요청이 브라우저에 캐시 될 수 있는 시간(초 단위)

 

👉 에러의 원인

 

서버에서 허용하는 Origin 목록에 해당 브라우저의 Origin이 없었기 때문

 

✔ Access-Control-Max-Age 설정을 하는 이유

 

보안 강화 목적으로 예비 요청을 사용하는 것은 바람직하지만 이로 인해 요청 횟수가 늘어나고 응답 속도가 느려져 성능 측면에선 불리한 요소가 된다.

그래서 Access-Control-Max-Age 헤더를 사용하여 캐시 될 시간을 명시하면 해당 예비 요청을 캐싱하여 최적화시킬 수 있다.

 

설정 후, 브라우저는 설정된 시간 동안 캐시에 결과를 저장하고, 다음 예비 요청 때 그 응답이 이미 캐시에 들어있다면 요청을 절약하는 방식으로 성능을 최적화하는 것이다.

 

🔍 단순 요청 (Simple Request)

 

예비 요청을 생략하고 바로 서버에 본 요청을 보낸 후, 서버가 이에 대한 응답 헤더에 Access-Control-Allow-Origin 헤더를 보내주면 브라우저의 Origin과 비교하여 CORS 위반 여부를 확인하는 방식이다.

 

단순 요청을 하는 경우는 다음과 같다.

 

  1. GET, POST, HEAD 요청
  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}

 

🔍 인증된 요청 (Credentialed Request)

 

클라이언트에서 서버에게 자격 인증 정보(Credential)를 실어 요청할 때 사용되는 요청이다.

 

자격 인증 정보: 쿠키, Authorization 헤더에 설정하는 토큰 값 등

 

📌 해결 방법 (Spring)

 

🔍 @CrossOrigin (Controller)

 

 

가장 간단한 방법으로 @CrossOrigin을 사용하면 CORS 정책을 설정할 수 있다. originPatterns로 설정한 URL은 Access-Control-Allow-Origin에 설정된다.

 

🔍 Spring 설정 파일에 설정 추가

 

@WebMvcConfigurer를 implements 했고, @Configuration이 달린 파일에서 서버의 헤더 필드를 설정하여 CORS 정책을 만족하도록 하는 방법이다.

 

 

🔍 Filter 에서 CORS 설정

 

 

References:

https://velog.io/@wogkr1383/SOP%EC%99%80-CORS

 

SOP와 CORS

📌 SOP와 CORS에 대해서 설명해주세요

velog.io

 

https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-CORS-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC-%ED%95%B4%EA%B2%B0-%EB%B0%A9%EB%B2%95-%F0%9F%91%8F

 

🌐 악명 높은 CORS 개념 & 해결법 - 정리 끝판왕 👏

악명 높은 CORS 에러 메세지 웹 개발을 하다보면 반드시 마주치는 멍멍 같은 에러가 바로 CORS 이다. 웹 개발의 신입 신고식이라고 할 정도로, CORS는 누구나 한 번 정도는 겪게 된다고 해도 과언이

inpa.tistory.com

 

https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy

 

Same-origin policy - Security on the web | MDN

The same-origin policy is a critical security mechanism that restricts how a document or script loaded by one origin can interact with a resource from another origin.

developer.mozilla.org

 

https://steady-coding.tistory.com/616

 

[Spring] Spring에서 CORS 이슈를 해결하는 방법

spring-study에서 스터디를 진행하고 있습니다. CORS(Cross-Origin Resource Sharing) CORS는 Cross-Origin Resource Sharing 의 줄임말로, 교차 출처 리소스 공유를 의미하며, 교차 출차는 ‘다른 출처’라고 생각하면

steady-coding.tistory.com

 

'Network' 카테고리의 다른 글

JWT vs Session  (0) 2024.01.26
JWT (JSON Web Token)  (4) 2024.01.25
HTTP 응답/상태 코드  (0) 2023.07.11
API vs HTTP API vs REST API  (0) 2023.07.10
HTTP 메서드  (0) 2023.07.10