현재 번역은 완벽하지 않습니다. 한국어로 문서 번역에 동참해주세요.

동일 출처 정책(same-origin policy)은 한 출처(origin)에서 로드된 문서나 스크립트가 다른 출처 자원과 상호작용하지 못하도록 제약한다.

출처의 정의

두 페이지의 프로토콜, 포트, 호스트가 같으면 동일 출처(same origin)이다. 아래의 표는 예로든 URL http://store.company.com/dir/page.html 의 출처를 비교한 것이다.

URL 결과 이유
http://store.company.com/dir2/other.html 성공  
http://store.company.com/dir/inner/another.html 성공  
https://store.company.com/secure.html 실패 프로토콜 상이
http://store.company.com:81/dir/etc.html 실패 포트 상이
http://news.company.com/dir/other.html 실패 호스트 상이

file: URL의 출처정의도 참고바람.

출처 상속

about:blank, javascript:, data: URL의 컨텐트는 URL을 로드한 문서의 출처를 상속받는다. 이런 URL들은 출처에 대한 정보가 없기 떄문이다.

IE 예외사항

인터넷 익스플로러(Internet Explorer)는 동일 출처 정책에 두가지 중요한 예외사항이 있다.

  • Trust Zones: 두 도메인이 highly trusted zone에 속하면(기업도메인 같은) 동일 출처 제약이 적용되지 않는다.
  • Port: IE는 포트는 비교하지 않는다. 따라서  http://company.com:81/index.html 와 http://company.com/index.html 은 동일출처로 여기며 제약이 적용되지 않는다.

위의 예외는 비표준이고 다른 브라우져에는 적용되지 않는다.

출처 변경

일부 제약이 있긴 하지만 페이지의 출처를 변경하는 것이 가능하다. 스크립트로 document.domain 의 값을 현재 도메인이나 현재 도메인의 상위 도메인으로 변경할 수 있다. 만약 도메인을 현재 도메인의 상위도메인으로 변경하면, 보다 짧은 도메인이 이후의 출처 확인에 사용된다. 예를 들어 http://store.company.com/dir/other.html 문서의 스크립트가 아래의 문장을 실행하면:

document.domain = "company.com";

문장이 실행된 이후에 페이지는 출처 체크에 http://company.com/dir/page.html 를 보낸다. 참고로, document.domain 의 값을 company.com 이 아닌 othercompany.com 으로 설정할 수는 없다. 왜냐하면 othercompany.com은 store.company.com의 상위 도메인이 아니기 때문이다.

포트 번호는 브라우저별로 유지된다. document.domain = document.domain 을 포함한 setter에 대한 모든 호출은 포트 번호를 null로 덮어쓸 것이다. 따라서 처음에 document.domain = "company.com" 만을 설정한다고 해서 company.com:8080 이 company.com 과 통신할 수는 없다. 양쪽 포트가 모두 null이 되도록 설정되어야 한다.

참고: 부모가 안전하게 접근하도록 하기 위해 document.domain을 사용한다면, 부모 도메인과 서브 도메인의 document.domain을 같은 값으로 설정해야 한다. 단순히 부모 도메인이 원래 값으로 설정되는 것이라고 해도 필수적이다. 이를 수행하는데 실패하면 권한 오류가 발생할 수도 있다.

Cross-origin 네트워크 접근

동일 출처 정책은 당신이 XMLHttpRequest 혹은<img> 요소를 사용할 때와 같은 두개의 다른 출처간의 상호작용을 조절한다. 이 상호작용들은 일반적으로 세개의 카테고리에 존재한다:

  • Cross-origin writes 는 일반적으로 허용된다. 링크, 리디렉션과 폼 sumissions가 그 예들이다. 아주 간혹 사용되는 특정 HTTP 요청에는 preflight가 필요하다.
  • Cross-origin embedding 은 일반적으로 허용된다. 아래에 예제들이 있다.
  • Cross-origin reads 는 일반적으로는 허용되지 않으나, 읽기 접근은 종종 임베딩에 의해 유출된다. 예를 들어 임베드된 이미지의 폭과 너비, 임베드된 스크립트의 액션, 임베드된 리소스의 가용성을 읽을 수 있다.

아래에는 임베드된 cross-origin 일지도 모르는 몇가지 리소스의 예제들이 있다:

  • <script src="..."></script>를 사용한 자바스크립트. 구문 오류에 의한 오류 메시지는 오직 같은 출처의 스크립트에서만 가능하다.
  • <link rel="stylesheet" href="...">을 사용한 CSS. CSS의 relaxed syntax rules 때문에, cross-origin CSS는 올바른 Content-Type 헤더가 필요하다. 제한은 브라우저에 따라 다르다: IE, Firefox, Chrome, Safari (CVE-2010-0051으로 스크롤 다운) 과 Opera.
  • <img> 을 사용한 이미지. 지원되는 이미지 포맷은 다음을 포함한다 : PNG, JPEG, GIF, BMP, SVG, ...
  • <video><audio> 를 사용한 미디어 파일.
  • <object>, <embed> 과 <applet>을 사용한 플러그인.
  • @font-face를 사용한 폰트. 몇몇 브라우저는 cross-origin 폰트를 허용하나, 그 외에는 동일 출처 폰트가 필요하다.
  • <frame> 과 <iframe>을 사용한 것. 사이트는 cross-origin 상호작용의 폼을 방지하기 위해 X-Frame-Options 헤더를 사용할 수도 있다.

Cross-origin 접근을 허용하는 방법

CORS 를 사용해 cross-origin 접근을 허용한다.

Cross-origin 접근을 방지하는 방법

  • cross-origin 쓰기를 막으려면, Cross-Site Request Forgery (CSRF) 토큰과 같이, 예측 불가능한 토큰을 요청에서 확인한다. 이 토큰을 알고있는 페이지에 대한 cross-origin 읽기는 무조건 막아야 한다.
  • cross-origin 리소스 읽기를 막으려면 그 리소스를 임베딩이 가능하지 않게 하면된다. 리소스가 임베딩되면 항상 그 정보가 새어나가는 것에 취약하기 때문에, 임베딩을 막는 것은 종종 필요하다.
  • cross-origin 임베딩을 막으려면, 리소스가 위의 임베딩 가능한 포맷 중의 하나로 해석될 수 없는지 확인한다. 대부분의 경우에 브라우저는 Content-Type을 지키지 않는다. 예를 들어 HTML 문서의 <script> 태그를 가리켰을 때, 브라우저는 HTML을 자바스크립트로 바꾸려고 할 것이다. 리소스가 사이트의 입구가 아닐 때에는 CSRF 토큰을 사용하여 임베딩을 방지할 수도 있다.

Cross-origin 스크립트 API 접근

JavaScript APIs such as iframe.contentWindow, window.parent, window.open and window.opener allow documents to directly reference each other. When the two documents do not have the same origin, these references provide limited access to the Window and Location objects. Some browsers allow access to more properties than the spec allows. You can use window.postMessage instead to communicate between documents.

Cross-origin 데이터 저장소 접근

Access to data stored in the browser such as localStorage and IndexedDB are separated by origin. Each origin gets its own separate storage, and JavaScript in one origin cannot read from or write to the storage belonging to another origin.

The window.name property can be used to temporarily store data, that can be accessed cross-origin.

Cookies use a separate definition of origins. A page can set a cookie for its own domain or any parent domain, as long as the parent domain is not a public suffix. Firefox and Chrome use the Public Suffix List to determine if a domain is a public suffix. Internet Explorer uses its own internal method to determine if a domain is a public suffix. The browser will make a cookie available to the given domain including any sub-domains, no matter which protocol (http/https) or port is used. When you set a cookie, you can limit its availability using the Domain, Path, Secure and Http-Only flags. When you read a cookie, you cannot see from where it was set. Even if you use only secure https connections, any cookie you see may have been set using an insecure connection.

함께 보기

원본 문서 정보

  • 저자: Jesse Ruderman

 

문서 태그 및 공헌자

 이 페이지의 공헌자: seungha-kim, ryuan.choi, manascue, Vermond, behumble
 최종 변경: seungha-kim,