CORS 개념

반응형

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

 

개념


개념을 알기전 먼저 ajax 다른 도메인서버의 자원을 요청 할 경우 이와 같은 에러를 만나게 된다.

(다른 페이지가 아니라 다른 도메인입니다 도메인 www.a.com 자원요청 -> www.b.com)

 

chrome(크롬)

No 'Access-Control-Allow-Origin' header is present on the requested resource. 
Origin ‘www.b.com' is therefore not allowed access.

 

 FireFox(파이어폭스)

교차 원본 요청 차단: 동일 출처 정책으로 인해 'www.b.com'에 있는 원격 자원을 읽을 수 없습니다. 
자원을 같은 도메인으로 이동시키거나 CORS를 활성화하여 해결할 수 있습니다.

 

외부로 요청이 안 되는 것은 자바스크립트 엔진 표준 스펙에 동일 출처 정책(same-origin policy)이라는 보안 규칙이 존재하기 때문이다.

 

자바스크립트 엔진 표준 스펙? 그럼 <script></script> 안에 있는 것말고

 

다른 도메인 서버의 <img> 파일이나 css 파일을 가져 올 있는 것인가?

정답은 맞습니다

<script></script> 안에 스크립트로 둘러 쌓인걸 "Cross-Site HTTP Requests" 라고 한다.

 

바로 그것이 자바스크립트 엔진 표준스펙에 존재하는 뭐다?

동일 출처 정책(same-origin policy)

 

우리에겐 아주 못된 악역이지만 역시 탄생 배경이 존재합니다.

 

 

사용 이유


예를 들어 정책이 없다는 것은? 그냥 아무나,누구나 도메인 서버에 와서 자원을 가져 갈 있는 것이다. 그렇다는건 비밀번호를 가로채는 스크립트를 만들어 자원을 쉽게 있다는 뜻이 된다.

 

한마디로 보안에 취약하다.

 

 

조건


프로토콜, 호스트명, 포트가같아야만 자원을 주고 받을 있다.

www.a.com -> www.a.com/a1 O

www.a.com/a1 -> www.a.com/a2 O



www.a.com -> www.b.com X

www.a.com/a1 -> www.b.com X

 

하지만 우리는 ajax 이용한 rest api 서비스를 굉장히 많이 사용하기 때문에

same-origin policy 부시고 CORS 허용 해줘야한다.


CORS(교차 출처 자원 공유(Cross Origin Resource Sharing))

 

개념


웹 브라우저에서 외부 도메인 서버와 통신하기 위한 방식을 표준화한 스펙이다. 서버와 클라이언트가 정해진 해더를 통해 서로 요청이나 응답에 반응할지 결정하는 방식으로 교차 출처 자원 공유(cross-origin resource sharing)라는 이름으로 표준화가 되었다.

 

한마디로 Cross-Site Http Request를 가능하게 해주는 표준 규약

 

 

종류


Simple Request

Preflight Request

Credential Request

Non-Credential Request

 

 

Simple Request


이는 다음 3가지를 만족해야 합니다.

1. GET, HEAD, POST 중 한 가지 방식을 사용

2. POST일 경우 Content-type이 아래 셋 중 하나를 만족

- application/x-www-form-urlencoded

- multipart/form-data

- text/plain

3. 커스텀 헤더를 전송하지 않아야 함

 

 

Preflight Request


이름에서 볼 수 있는 것처럼 Preflight(예비) 요청을 먼저 보내고 서버가 이에

응답이 가능한 지 확인합니다. 예비 요청은 OPTION메서드로 HTTP 요청을 전송합니다.

 

이후 실제 Actual(본) 요청을 보냅니다.

그리고 서버가 이에 응답하며 통신하는 형태이죠.

Preflight Request는 위의 Simple Request에 해당하는 조건에 만족하면 안돼요.

그렇기에 GET, HEAD, POST 이외 메서드를 사용하는 경우에만 사용 가능한 요청입니다

 

만약 POST 요청을 사용할 경우에는 Content Type이 위의 3가지 경우가 아니거나 

(application/json)

또는 커스텀 헤더를 사용할 경우에 사용할 수 있다는 점을 기억해야 합니다.

예비 요청과 예비 응답, 본 요청과 본 응답 총 4번의 형태로 구성되어 있습니다.

 

순서

Client 예비(method = OPTIONS) 전송-> Server OPTIONS 확인하고 서버쪽 CORS 허용 돼있으면 요청에 답함

(그렇지 않으면 405 Method Not Allowed HTTP 반환)

 

 

Credential


HTTP Cookie와 HTTP Authentication 정보를 인식할 수 있게 해주는 요청

 

요청 시 xhr.withCredentials = true를 지정하는 것이 가장 큰 특징

Access-Control-Allow-Credentials: true

만약 위의 설정이 false라면? 브라우저는 이 요청을 거부할 것입니다.

 

 

Non-Credential


 

사실 withCredentials 플래그는 디폴트 값이 false입니다.

그러니 위의 Credential 요청에서와 같이 처리해주지 않는다면 모든 요청이 바로

 

Non-Credential에 해당된다고 볼 수 있습니다.

 

 

방식


1.jsonp 방식

위에서 설명했듯이 css,img,js 파일은 동일 출처 정책에 걸리지 않는다.

그러므로 <script></script> 스크립트를 json 형식으로 변경 읽어오는 방법

하지만 GET 방식만 요청이 가능하다.

 

2. 웹브라우저 외부 요청 허용 옵션 사용

-disable-web-security 옵션을 추가하여 크롬 실행

 

1,2번은 추천하지 않습니다. 2번은 더더욱

일반 사용자들에게 -disable-web-security 옵션을 써서 브라우저를 실행 시키라고 하는 것은 말도 안되죠

 

3.CORS 요청 핸들링

Access-Control-Allow-Origin: *

Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS

Access-Control-Max-Age: 3600

Access-Control-Allow-Headers: Origin,Accept,X-Requested-With,Content-Type,Access-Control-Request-Method,Access-Control-Request-Headers,Authorization

 

간단 설명


Request headers (클라이언트의 요청 해더)  

Origin: 요청을 보내는 페이지의 출처(도메인) 

Access-Control-Request-Method: 실제 요청하려는 메서드 

Access-Control-Request-Headers: 실제 요청에 포함되어 있는  해더 이름

 

Response headers (서버에서의 응답 해더)

Access-Control-Allow-Origin: 요청을 허용하는 출처. * 이면 모든 곳에 공개되어 있음을 의미한다. 

Access-Control-Allow-Credentials: 클라이언트 요청이 쿠키를 통해서 자격 증명을 해야 하는 경우에 true. true를 응답받은

클라이언트는 실제 요청 시 서버에서 정의된 규격의 인증값이 담긴 쿠키를 같이 보내야 한다.

 

Access-Control-Expose-Headers: 클라이언트 요청에 포함되어도 되는 사용자 정의 해더.

 

Access-Control-Max-Age: 클라이언트에서 preflight의 요청 결과를 저장할 기간을 지정.

클라이언트에서 preflight 요청의 결과를 저장하고 있을 시간이다. 해당 시간 동안은 preflight요청을 다시 하지 않게 된다.

 

Access-Control-Allow-Methods: 요청을 허용하는 메서드. 기본값은 GET, POST라고 보면 된다.

이 해더가 없으면 GET과 POST 요청만 가능하다. 만약 이 해더가 지정이 되어 있으면,

클라이언트에서는 해더 값에 해당하는 메서드일 경우에만 실제 요청을 시도하게 된다.

 

Access-Control-Allow-Headers: 요청을 허용하는 해더.

 

 

조건


Client Access-Control-Allow-Origin 허용 해줘야하고,

Server Access-Control-Allow-Origin 허용 해줘한다

 

한마디로 Client-Server 양쪽 모두 허용해줘야 통신이 가능하다.

 

저는 Client 웹에만 허용을 주구장창하고 API 서버에는 허용을 안했습니다.

그러고 삽질을 엄청했죠 지구의 맨틀까지 보일뻔 보일 뻔했습니다 너무 삽질해서…

 

이런 개념말고 허용해주는 코드를 달라고요??

그건 따로 Java 탭에서 다루겠습니다.

 

반응형

+ Recent posts