용어 | CORS, SOP : 교차 출처 리소스 공유

|

요약

CORS : 교차 출처 리소스 공유 | Cross Origin Resource Sharing
다른 출처의 자료가 브라우저에 접근할 때 권한을 부여하는 기능

SOP : 동일 출처 정책 | Same-Origin Policy
다른 출처의 자료가 브라우저에 접근하지 못하도록 막는 기능

2011년 RFC 6454에서 처음 등장한 보안정책들입니다. 이 두개 모두 악의를 가진 해커로부터 보호하기 위해 만들어졌습니다.

AJAX 요청에 다른 웹사이트 값을 가져오면 CORS 에러가 뜨게 됩니다. 이는 브라우저에서 막고 있습니다.
승인되지 않으면 접근할 수 없기 때문에 접근을 처리할 때 추가적인 작업을 해야 합니다.

Cross 라는 단어는 “다른 출처” 를 의미하는데요, 다른 출처의 사이트 자료를 가져옵니다.

프리플라이트 Prefilght

image 121
출처 : CORS는 왜 이렇게 우리를 힘들게 하는걸까? | Evans Library (evan-moon.github.io)

프리플라이트는 CORS spec이 생기기 전에 만들어진 서버들은 브라우저의 SOP request 만 가능하다는 가정하에 설계되었습니다. 이 서버들은 cross-site request(CSRF) 의 보안 매커니즘이 없습니다.

프리플라이트 요청(Preflight request) 으로 서버가 CORS를 인식하고 핸들링할 수 있는지 먼저 확인한 다음 CORS를 인식하지 못하는 서버를 보호할 수 있습니다.

  • 예비요청에서 본 요청 순서로 서버로 전송합니다.
  • 브라우저가 보내는 예비요청을 Preflight 라고 합니다.
  • 예비요청에는 HTTP 메소드중 OPTIONS 메소드가 사용됩니다. (안전한지 파악)

어떻게 작동되나?

CORS 정책을 위반했다고 판단하는 기준은
예비 요청에 대한 응답 헤더 값에 Access-Control-Allow-Origin 값이 유효한가에 있습니다.

만약 예비요청이 실패하여 200이 아닌 상태코드가 들어와도 헤더에 값만 잘 들어있다면 CORS 정책 위반이 아닙니다.

코드

아래의 코드는 CORS는 왜 이렇게 우리를 힘들게 하는걸까? 의 내용을 인용했습니다.

프론트엔드 영역

const headers = new Headers({
  'Content-Type': 'text/xml',
});
fetch('https://evanmoon.tistory.com/rss', { headers });

RSS 파일 리소스에 요청을 보내면 브라우저가 본 요청을 보내기 전에 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

결과

🚨 Access to fetch at ‘https://evanmoon.tistory.com/rss’ from origin ‘https://evan-moon.github.io’ has been blocked by CORS policy: Response to preflight request doesn’t pass access control check: The ‘Access-Control-Allow-Origin’ header has a value ‘http://evanmoon.tistory.com’ that is not equal to the supplied origin. Have the server send the header with a valid value, or, if an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.

출처 Origin

https://example.com/users?sort=asc&page=1#foo

  • https://
    프로토콜 (Protocol)
  • example.com
    호스트 (Host)
  • /users
    패스 (Path)
  • ?sort=asc&page=1
    쿼리 정보 (Query String)
  • #foo
    프래그먼트 (Fragment)

여기서 보이지는 않지만 :80 :443 과 같은 포트번호가 생략되어 있습니다.
출처는 서버의 위치를 찾아가기 위해 필요한 가장 기본적인 것들을 합쳐놓은 것입니다.

예외 조항

SOP 정책에는 스크립트, 스타일 시트, 렌더링 될 이미지는 다른 출처의 리소스에 접근할 수 있습니다.
이것은 웹 폰트 혹은 외부 이미지를 가져오는 등의 방법을 사용될 수 있습니다.

Access-Control-Allow-Origin

라라벨에서 사용하기

CORS 설정(라라벨 7 이후 등장) 과 HandleCors 미들웨어를 활용합니다.

config\cors.php 에 설정값을 확인할 수 있습니다

참조

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

클릭하여 복사