CORS란
Cross-Origin Resource Sharing 의 약자로 한글로는
" 교차 출처 리소스 공유 정책 " 이라고 해석할 수 있는데, 여기서
교차 출처 라는것은 ( 엇갈린 ) 다른 출처 라는 의미로 보면 된다.
XMLHttpReqeust,Fetch API 스크립트
기본적으로 Same-Origin 정책을 따름.
다른 도메인의 소스에 대해 자바스크립트 Ajax 요청 API 호출 시,
웹 폰트 CSS 파일 내 @font-face에서 다른 도메인의 폰트 사용 시
- 자바스크립트에서의 요청은 기본적으로 서로 다른 도메인에 대한 요청을 보안상 제한한다.
브라우저는 기본적으로 하나의 서버 연결만 허용되도록 설정되어 있기 때문이다
출처 ( Origin ) 란?
우리가 어떤 사이트를 접속할때 인터넷 주소창에 우리는 URL 이라는 문자열을 통해 접근하게 된다.
이처럼 URL 은 https://domain.com:3000/user?query=name&page=1 과 같이 하나의 문자열 같지만, 사실은 다음 과 같이 여러개의 구성 요소로 이루어져 있다.
- Protocol ( Schema ) : http,https
- Host : 사이트 도메인
- Port : 포트 번호
- Path : 사이트 내부 경로
- Query String : 요청의 key와 value값
- Fragment : 해시 태그
여기서 출처 ( Origin ) 이란 Protocol + Host + Port를 모두 합친 URL을 의미한다고 보면 된다.
동일 출처 정책 ( SOP Same-Origin Policy )]
SOP는 단어 그대로 동일한 출처에 대한 정책을 말한다. 그리고 이 SOP 정책은
" 동일한 출처에서만 리소스를 공유할 수 있다 " 라는 법률을 가지고 있다.
즉 동일 출처의 서버에 있는 리소스는 자유로이 가져올 수 있지만 다른 출처 ( Croos-Origin ) 서버에 있는 리소스는 상호 작용이 불가능하다 라는 뜻
동일 출처 정책이 필요한 이유
출처가 다른 두 애플리케이션이 자유로이 소통 할 수 있는 환경은 굉장히 위험한 환경이다. 만일 제약이 없다면
해커가 CSRF ( Cross-Site Reqeust Forgery )나 XSS( Cross-Site Scripting ) 등의 방법을 이용해서 우리가 만든 애플리케이션에서 해커가 심어놓은 코드가 실행하여 개인 정보를 가로챌 수 있다.
같은 출처와 다른 출처의 구분
출처 ( Origin ) 의 동일함은 URL 의 구성요소중 Protocol (Schema),Host,Port 이 3가지가 동일하면 된다.
교차 출처 리소스 공유 ( Cross-Origin Resource Sharing )
이처럼 교차 출처 리소스 공유란 한마디로 다른 출처의 리소스 공유에 대한 허용 / 비허용 정책을 말한다
보안이 중요하지만, 개발을 하다보면 기능상 어쩔 수 없이 다른 출처 간의 상호작용을 해야 하는 케이스도 있으며,
또한 실무적으로 다른 회사의 서버 API를 이용해야 하는 상황도 존재한다 따라서 이와 같은 예외 사항을 두기 위해 CORS 정책을 허용하는 리소스에 한해 다른 출처도 받아들인다는 것이다.
- 요약하면 SOP 정책을 위반해도 CORS 정책에 따르면 다른 출처의 리소스라도 허용된다 라는 것이다.
브라우저의 CORS 기본 동작
- 클라이언트에서 HTTP 요청의 헤더에 Origin을 담아 전달
- 브라우저는 요청 헤더에 Origin 이라는 필드에 출처를 함께 담아 보낸다.
- 서버는 응답 헤더에 Access-Control-Allow-Origin을 담아 클라이언트로 전달
- 이후 서버가 이 요청에 대한 응답을 할 때 응답 헤더에 Access-Control-Allow-Origin 이라는 필드를 추가하고 값으로 ' 이 리소스를 접근하는 것이 허용된 출처 URL ' 을 내려 보낸다.
- 클라이언트에서 Origin과 서버가 보내준 Access-Control-Allow-Origin을 비교한다.
- 응답을 받은 브라우저는 자신이 보냈던 요청의 Origin과 서버가 보내준 응답의 Access-Control-Allow-Origin을 비교해본 후 차단할지 말지를 결정한다.
- 만약 유효하지 않다면 그 응답을 사용하지 않고 버린다. ( CORS 에러 발생 )
CORS 해결책은 서버에서 Access-Control-Allow-Origin 헤더에 허용할 출처를 기재해 클라이언트에 응답하는 것
CORS 작동방식 3가지 시나리오
위의 CORS 동작 흐름은 기본적인 작동 흐름을 보여준 것이고,
실제 CORS의 동작 방식은 한 가지가 아니라 세 가지의 시나리오에 따라 변경된다.
예비 요청 ( Preflight Request )
브라우저는 요청을 보낼때 한번에 바로 보내지 않고, 먼저 예비 요청을 보내 서버와 잘 통신되는지 확인 후 본 요청을 보낸다.
즉, 예비 요청의 역할은 본 요청을 보내기 전에 브라우저 스스로 안전한 요청인지 미리 확인하는 것이다.
이 예비 요청의 HTTP 메소드는 GET이나 POST가 아닌 OPTIONS라는 메서드가 사용되는것이 특징이다.
예비 요청의 문제점과 캐싱
- 요청을 보내기 전 OPTIONS 메서드로 예비 요청을 보내 보안을 강화하는 목적의 취지는 좋다. 그러나 결국은 실제 요청에 걸리는 시간이 늘어나게 되어 애플리케이션 성능에 영향을 미치는 크나큰 단점이 있다.
- 특히 수행하는 API 호출 수가 많아 질수록 예비 요청으로 인해 서버 요청을 배로 보내게 되니 비용적인 측면에서 폐가 될 수 있다. 따라서 브라우저 캐시(Cache)를 이용해 Access-Control-Max-Age 헤더에 캐시될 시간을 명시해 주면, 이 Preflight 요청을 캐싱 시켜 최적화를 시켜줄 수 있다.
단순 요청 ( Simple Request )
말 그대로 에비 요청 ( Prefilght )을 생략하고 바로 서버에 직행으로 본 요청을 보낸 후, 서버가 이에 대한 응답의 헤더에 Access-Control-Allow-Origin 헤더를 보내주면 브라우저가 CORS 정책 위반 여부를 검사하는 방식
심플한 만큼 특정 조건을 만족하는 경우에만 예비 요청을 생략할 수 있다.
대표적으로 아래 3가지의 경우를 만족할 때만 가능하다.
- 요청의 메소드는 GET,HEAD,POST중 하나
- Accept , Accept-Language , Content-Language, Content-Type , DPR,Downlink,Save-Data,Viewport-Width,Width 헤더일 경우에만 적용된다.
- Content-Type 헤더가 application / x-www-form-urlencoded, multipart/form-data , text/plain 중 하나여야 한다. 아닐 경우에는 예비요청으로 작동한다
대부분 HTTP API 요청은 text/xml 이나 application/json 으로 통신하기 때문에 3번째를 위반하는 경우가 많다.
따라서 대부분의 API 요청은 예비요청 ( Preflight ) 으로 이루어진다고 이해하면 된다.
인증된 요청 ( Credentialed Request )
클라이언트에서 서버에게 자격 인증 정보 ( Credential ) 를 실어 요청할때 사용되는 요청.
여기서 말하는 자격 인증 정보란 세션 ID가 저장되어있는 쿠키( Cookie ) 혹은 Authorization 헤더에 설정하는
토큰( Token )값 등을 일컫는다.
즉, 클라이언트에서 일반적인 JSON 데이터 외에도 쿠키 같은 인증 정보를 포함해서 다른 출처의 서버로 전달할때CORS의 세가지 요청중 하나인 인증된 요청으로 동작된다는 말이며, 이는 기존의 단순 요청이나 예비 요청과는 살짝 다른 인층 형태로 통신하게 된다.
클라이언트에서 인증 정보를 보내려면 credentials 옵션을 사용하면 된다.이 옵션에는 3가지의 값을 사용할 수 있으며, 각 값들이 가지는 의미는 아래와 같다
옵션 값 | 설명 |
same-origin ( 기본 값 ) | 같은 출처 간 요청에만 인증 정보를 담을 수 있다. |
include | 모든 요청에 인증 정보를 담을 수 있다. |
omit | 모든 요청에 인증 정보를 담지 않는다. |
인증 요청을 보내는 방법은 ajax,axios,fetch 등등 각각 라이브러리 별로 다르기 때문에 잘 찾아보고 사용해야 한다.
'CS지식' 카테고리의 다른 글
oAuth 2.0 개념정리 (0) | 2024.04.04 |
---|---|
CS 공부 - HTTP (0) | 2023.04.02 |
CS 공부 -Spring (0) | 2023.03.23 |
기술면접 DB (0) | 2023.03.19 |
HTTP 동작원리 (0) | 2023.03.15 |