'CORS'에 해당되는 글 2건

  1. 2014.02.03 XMLHttpRequest
  2. 2014.01.21 동일출처정책(Same-origin policy) (2)
기타/웹 2.02014. 2. 3. 13:17

이 글은 영문 Wikipedia의 글을 번역한 것입니다. 제가 공부하기 위한 목적으로 번역한 것이므로, 오류가 있을 수도 있습니다. 문제 있는 부분을 발견하시면 댓글로 남겨주시면 감사하겠습니다.


===

XMLHttpRequest(XHR)은 Javascript와 같은 웹브라우저 스크립트 언어에서 사용할 수 있는 API이다. XHR은 웹서버에 HTTP 혹은 HTTPs 요청을 전송하고 서버의 응답을 다시 스크립트로 불러오는데 사용된다. 모든 주류 웹브라우저의 개발버전에서는 http: 와 https: 이외의 URI 도 지원한다. 특히 blob:URL 이 지원된다.


XMLHttpRequest (XHR) is an API available to web browser scripting languages such as JavaScript. It is used to send HTTP or HTTPS requests to a web server and load the server response data back into the script. Development versions of all major browsers support URI schemes beyond http: and https:, in particular, blob: URLs are supported.


이 API는 호환성 확보를 위해 XMLHttpRequest라는 명칭으로 표준화되었다. 하지만 이 명칭은, XML 뿐만 아니라 임의의 텍스트도 전송받을 수 있다는 점에서 오해를 불러일으킬 소지가 있다. 데이터를 JSON, HTML 또는 일반 텍스트로 수신하는 경우도 많다. 응답받은 데이터를 이용하여 새로운 페이지를 불러들이지 않고 현재의 문서를 변경시킬 수 있다. 또한 응답 데이터를 클라이언트측 스크립트에서 평가할 수도 있다. 예를 들어, 웹서버에서 JSON 포맷으로 받았다면, 이를 클라이언트측에서 객체로 변환할 수 있다.


The name was standardized to XMLHttpRequest for compatibility. It may be misleading, in particular because any textual data may be received from the server, not just XML. Data are also commonly received as JSON, HTML, or as plain text. Data from the response can be used to alter the current document in the browser window without loading a new web page. The response data can also be evaluated by client-side scripting. For example, if it was formatted as JSON by the web server, it can be converted into a client-side data object for further use.


XMLHttpRequest 는 AJax 웹 개발 기법에서 중요한 역할을 담당하고 있으며, 많은 웹사이트에서 반응형 동적 웹을 구현하는데 사용되고 있다.


XMLHttpRequest has an important role in the Ajax web development technique. It is currently used by many websites to implement responsive and dynamic web applications.


XMLHttpRequest는 브라우저의 동일출처정책(same-origin policy)의 제한을 받는다. 즉, 보안을 이유로 원래의 웹페이지를 보낸 동일한 서버에 대한 요청만 가능하다.


XMLHttpRequest is subject to the browser's same-origin policy: for security reasons, requests will only succeed if they are made to the same server that served the original web page.


역사와 지원(History and Support)


XMLHttpRequest 객체의 개념은 원래 Outlook Web Access 개발자가 Microsoft Exchange Server 2000을 위하여 고안하였다. 이 개념을 사용하여 MSXML 라이브러리 버전 2에 IXMLHTTPRequest 라는 인터페이스가 개발 구현되었다. MSXML 라이브러리 버전 2는 1999년 3월 Internet Explorer 5.0 에 탑재되었는데, ActiveX를 통해, MSXML 라이브러리의 XMLHTTP wapper를 사용하여 IXMLHTTPRequest 인터페이스로 접근할 수 있었다.


The concept behind the XMLHttpRequest object was originally created by the developers of Outlook Web Access (by Microsoft) for Microsoft Exchange Server 2000.[6] An interface called IXMLHTTPRequest was developed and implemented into the second version of the MSXML library using this concept.[6][7] The second version of the MSXML library was shipped with Internet Explorer 5.0 in March 1999, allowing access, via ActiveX, to the IXMLHTTPRequest interface using the XMLHTTP wrapper of the MSXML library.


Mozilla 프로젝트에서는 Gecko 레이아웃 엔진에 nsIXMLHttpRequest라는 인터페이스를 개발 구현하였다. 이 인터페이스는 마이크로소프트의 IXMLHTTPRequest 인터페이스와 가능한 한 비슷하게 작동하도록 설계되었다. Mozilla는 자바스크립트 엔진을 통해 이 인터페이스를 사용할 수 있는 wrqpper를 만들어 이를

XMLHttpRequest 라고 하였다. XMLHttpRequest 객체는 2000년 12월 6일 출시된 Gecko 버전 0.6 부터 접근할 수 있었으나, 2002년 6월 5일 출시된 Gecko 1.0 버전이 나오면서부터 완전하게 작동되었다. XMLHttpRequest 객체는 기타 주요 웹 클라이언트에서 사실상의 표준이 되어, 2004년 2월 출시된 Safari 1.2, Konqueror, 2005년 4월 출시된 Opera 8.0, 2005sus 9월 출시된 iCab 3.0b352 등에서 구현되었다.


The Mozilla project developed and implemented an interface called nsIXMLHttpRequest into the Gecko layout engine. This interface was modeled to work as closely to Microsoft's IXMLHTTPRequest interface as possible. Mozilla created a wrapper to use this interface through a JavaScript object which they called XMLHttpRequest. The XMLHttpRequest object was accessible as early as Gecko version 0.6 released on December 6 of 2000, but it was not completely functional until as late as version 1.0 of Gecko released on June 5, 2002. The XMLHttpRequest object became a de facto standard in other major web clients, implemented in Safari 1.2 released in February 2004, Konqueror, Opera 8.0 released in April 2005, and iCab 3.0b352 released in September 2005.


W3C 컨소시움에서는 2006년 4월 5일, Opera Sottware의 Anne van Kesteren 과 W3C의 Dean Jackson이 편집한 XMLHttpRequest 객체 사양 초안(working draft)을 발행했다. 이 문서의 목적은 "기존의 구현을 기초로 상호 운영할 수 있는 최소한의 기능을 문서화함으로써, 웹 개발자들이 플랫폼에 독립적으로 사용할 수 있도록 하기 위한 것"이었다. XMLHttpRequest 객체 사양이 최후로 개정된 것은 2009년 11월 19일이었으며, 현재 마지막 초안(last call working draft)인 상태이다.


The World Wide Web Consortium published a Working Draft specification for the XMLHttpRequest object on April 5, 2006, edited by Anne van Kesteren of Opera Software and Dean Jackson of W3C.[17] Its goal is "to document a minimum set of interoperable features based on existing implementations, allowing Web developers to use these features without platform-specific code." The last revision to the XMLHttpRequest object specification was on November 19 of 2009, being a last call working draft.


마이크로소프트에서는 2006년 10월 발매된 Internet Explorer 7.0 용 스크립트언어에 XMLHttpRequest 객체 구별자를 추가하였다.


Microsoft added the XMLHttpRequest object identifier to its scripting languages in Internet Explorer 7.0 released in October 2006.


jQuery나 Prototype Javascript Framework와 같은 브라우저 독립적 자바스크립트 라이브러리가 출현하면서 개발자들은 API를 직접 코딩하지 않고도 XMLHttpRequest 기능을 호출할 수 있게 되었다. Prototype은 Ajax.Request라는 비동기 호출객체(requester object)를 제공한다. 이 객체는 브라우저의 구현을 포장하여 접근할 수 있도록 해준다. jQuery 객체는 현재의 클라이언트측 DOM으로부터 요소를 표현하거나 포장한다. 이들은 모두 .load() 메소드를 가지고 있어, URI 파라미터를 받아 해당 URI에 XMLHttpRequest 를 전송하고, 기본적으로 반환되는 HTML을 jQuery 객체로 표현되는 HTML 요소에 저장한다.


With the advent of cross-browser JavaScript libraries such as jQuery and the Prototype JavaScript Framework, developers can invoke XMLHttpRequest functionality without coding directly to the API. Prototype provides an asynchronous requester object called Ajax.Request that wraps the browser's underlying implementation and provides access to it. jQuery objects represent or wrap elements from the current client-side DOM. They all have a .load() method that takes a URI parameter and makes an XMLHttpRequest to that URI, then by default places any returned HTML into the HTML element represented by the jQuery object.


W3C는 그 이후 2008년 2월 25일에 "XMLHttpRequest Level 2"라고 하는, XMLHttpRequest 객체를 위한 또다른 사양 초안을 발표하였다. Level 2에는 progress 이벤트, 교차출처 요청의 지원, byte stream의 처리 등을 포함한 여러가지 기능이 추가되었다. XMLHttpRequest Level 2 의 최신버전은 2011년 8월 16일 발행되었으며 아직도 초안(working draft)인 상태이다.


The W3C has since published another Working Draft specification for the XMLHttpRequest object, "XMLHttpRequest Level 2", on February 25 of 2008.[23] Level 2 consists of extended functionality to the XMLHttpRequest object, including, but not currently limited to, progress events, support for cross-site requests, and the handling of byte streams. The latest revision of the XMLHttpRequest Level 2 specification is that of 16 August 2011, which is still a working draft.


2011년 12월 5일부로 XMLHttpRequest 버전 2는 XMLHttpRequest 사양에 통합되어, 이제 버전 1과 버전2는 존재하지 않는다.


As of 5 December 2011, XMLHttpRequest version 2 has been merged into the main XMLHttpRequest specification, and there is no longer a version 1 and a version 2.


HTTP 요청(HTTP Request)


아래 절은 XMLHttpRequest 객체를 사용한 요청이 W3C 초안에 따르는 브라우저 내에서 어떻게 기능하는지를 보여주는 예이다. XMLHttpRequest 객체에 대한 W3C 표준은 아직도 초안이므로, 웹브라우저가 W3C 에서 정의한 기능을 모두 준수하지 않을 수 있고, 아래의 내용은 언제든지 변경될 수 있다. 여러 웹브라우저에 대해 XMLHttpRuest 객체를 사용할 경우에는 각별히 주의를 기울여야 한다. 이 글은 주요 브라우저간의 불일치에 대해서도 가능한한 기술하고자 한다.


The following sections demonstrate how a request using the XMLHttpRequest object functions within a conforming user agent based on the W3C Working Draft. As the W3C standard for the XMLHttpRequest object is still a draft, user agents may not abide by all the functionings of the W3C definition and any of the following is subject to change. Extreme care should be taken into consideration when scripting with the XMLHttpRequest object across multiple user agents. This article will try to list the inconsistencies between the major user agents.


open 메소드


XMLHttpRequest 객체의 HTTP 및 HTTPS 요청은 반드시 open 메소드를 이용해 초기화해야 한다. 요청 메소드, URL, 요청에 사용되는 URI 사용자 정보등을 인증하고 해결하기 위해서 실제로 요청을 보내기 전에 반드시 이 메소드를 호출해야 한다. 이 메소드가 URL의 존재나 사용자 정보의 정확성을 보증하는 것은 아니다. 이 메소드는 최대 5개까지의 매개변수를 받을 수 있으나, 요청을 초기화하기 위해서는 2개의 매개변수만 필수이다.


The HTTP and HTTPS requests of the XMLHttpRequest object must be initialized through the open method. This method must be invoked prior to the actual sending of a request to validate and resolve the request method, URL, and URI user information to be used for the request. This method does not assure that the URL exists or the user information is correct. This method can accept up to five parameters, but requires only two, to initialize a request.


open( Method, URL, Asynchronous, UserName, Password )


처음 매개변수는 사용할 HTTP 요청을 나타내는 문자열이다. W3C 의 XMLHttpRequest 객체에 대한 표준 표준을 준수하는 웹 브라우저가 반드시 지원해야 하는 요청 방법은 현재 다음과 같다.


The first parameter of the method is a text string indicating the HTTP request method to use. The request methods that must be supported by a conforming user agent, defined by the W3C draft for the XMLHttpRequest object, are currently listed as the following.


  • GET (Supported by Internet Explorer 7 (and later), Mozilla 1+)
  • POST (Supported by Internet Explorer 7 (and later), Mozilla 1 (and later))
  • HEAD (Supported by Internet Explorer 7 (and later))
  • PUT
  • DELETE
  • OPTIONS (Supported by Internet Explorer 7 (and later))


그러나, 이 이외의 요청도 가능하다. W3C 초안에는 브라우저가 자신의 재량에 따라 추가 요청방법을 지원해도 좋다고 기술되어 있다.


However, request methods are not limited to the ones listed above. The W3C draft states that a browser may support additional request methods at their own discretion.


두번째 매개변수도 문자열로, HTTP 요청을 보낼 URL이다. W3C에서는 현재의 문서에서 포트번호가 다르거나 ihost URI 부분이 다를 경우 URL 에러를 발생시키고 URL 요청을 허용하지 말것을 권고하고 있다.


The second parameter of the method is another text string, this one indicating the URL of the HTTP request. The W3C recommends that browsers should raise an error and not allow the request of a URL with either a different port or ihost URI component from the current document.


세번째 매개변수는 동기/비동기인지를 나타내는 불리언 값으로, W3C 초안에서는 필수 매개변수가 아니다. 이 매개변수가 전달되지 않을 경우, 기본값은 true 이다. 비동기 요청("true")은 서버의 응답을 기다리지 않고 현재 스크립트의 실행을 계속한다. 그대신 요청에 따른 여러가지 단계별로 XMLHttpRequest 객체에 등록한 onreadystatechange 이벤트 리스너를 호출된다. 동기 요청("false")의 경우엔 요청이 완료될 때까지 현재의 스크립트의 수행이 정지된다. 따라서 onreadystatechange 이벤트리스너는 호출되지 않는다.


The third parameter, a boolean value indicating whether or not the request will be asynchronous, is not a required parameter by the W3C draft. The default value of this parameter should be assumed to be true by a W3C conforming user agent if it is not provided. An asynchronous request ("true") will not wait on a server response before continuing on with the execution of the current script. It will instead invoke the onreadystatechange event listener of the XMLHttpRequest object throughout the various stages of the request. A synchronous request ("false") however will block execution of the current script until the request has been completed, thus not invoking the onreadystatechange event listener.


네번째 다섯번째 매개변수는 username 과 password 이다. 이들 매개변수(혹은 username만)는 서버에서 인증목적으로 요구할 때 제공될 수 있다.


The fourth and fifth parameters are the username and password, respectively. These parameters, or just the username, may be provided for authentication and authorization if required by the server for this request.


setRequestHeader 메소드


요청을 성공적으로 초기화한 후, 요청과 함께 전송할 HTTP 헤더를 보내기 위해 XMLHttpRequest 객체의 setRequestHeaderMethod를 호출할 수 있다.


Upon successful initialization of a request, the setRequestHeader method of the XMLHttpRequest object can be invoked to send HTTP headers with the request.


setRequestHeader( Name, Value )


이 메소드의 첫번째 매개변수는 헤더를 가리키는 문자열이다. 두번째 매개변수는 문자열의 값이다. 이 메소드는 요청시 전송해야 하는 헤더별로 각각 호출해야 한다. 여기에서 첨부된 헤더는 W3C 표준을 따르는 브라우저에서 open 메소드가 다시 호출되면 삭제된다.


The first parameter of this method is the text string name of the header. The second parameter is the text string value. This method must be invoked for each header that needs to be sent with the request. Any headers attached here will be removed the next time the open method is invoked in a W3C conforming user agent.


send 메소드


HTTP 요청을 전송하려면 XMLHttpRequest 의 send 메소드를 호출해야 한다. 이 메소드는 요청할 내용을 담고 있는 하나의 매개변수가 필요하다.


To send an HTTP request, the send method of the XMLHttpRequest must be invoked. This method accepts a single parameter containing the content to be sent with the request.


send( Data )



보낼 내용이 없을 경우 이 매개변수는 생략할 수 있다. W3C 초안에 따르면 이 매개변수는 문자열로 변환될 수 있는 한 스크립트 언어가 지원하는 어떠한 타입도 무방하다. 단, DOM 문서 요소는 예외이다. 브라우저에서 매개변수를 시리얼화(serialize, 문자열 변환) 할 수 없다면 매개변수가 무시된다. Firefox 3.0.x 이전 버전의 경우, 매개변수가 없으면 예외가 발생한다.


This parameter may be omitted if no content needs to be sent. The W3C draft states that this parameter may be any type available to the scripting language as long as it can be turned into a text string, with the exception of the DOM document object. If a user agent cannot serialise the parameter, then the parameter should be ignored. Firefox 3.0.x and previous versions will however throw an exception if send is called without an argument.


매개변수가 DOM 문서 객체일 경우, 문서객체의 inputEncoding 프로퍼티에서 지정한 인코딩 방식을 사용하여 브라우저가 문서를 XML로 변환할 수 있어야 한다. setRequestHeader를 사용하여 Content-Type 헤더를 추가하지 않았을 경우, 브라우저가 "application/xml;charset=charset,"를 추가시켜야 한다. 여기에서 charset은 해당문서를 인코딩할때 사용된 인코딩이다.


If the parameter is a DOM document object, a user agent should assure the document is turned into well-formed XML using the encoding indicated by the inputEncoding property of the document object. If the Content-Type request header was not added through setRequestHeader yet, it should automatically be added by a conforming user agent as "application/xml;charset=charset," where charset is the encoding used to encode the document.


브라우저가 프록시 서버를 사용할 경우, XMLHttpRequest 객체는 받은 요청을 원래의 서버 대신 프록시로 연결되도록 적절히 변경하고, 설정된 바에 따라 프록시-인증(Proxy-Authorization)헤더를 전송한다.


If the user agent is configured to use a proxy server, then the XMLHttpRequest object will modify the request appropriately so as to connect to the proxy instead of the origin server, and send Proxy-Authorization headers as configured.


onreadystatechange 이벤트 리스너


If the open method of the XMLHttpRequest object was invoked with the third parameter set to true for an asynchronous request, the onreadystatechange event listener will be automatically invoked for each of the following actions that change the readyState property of the XMLHttpRequest object.


XMLHttpRequest 객체의 open 메소드가 비동기로 호출되었을 경우 (세번째 매개변수가 true로 설정), XMLHttpRequest 객체의 readyState 프로퍼티를 변경시키는 다음과 같은 상황이 발생될 때마다 onreadystatechange 이벤트 리스너가 자동적으로 호출된다.


  • open 메소드가 성공적으로 호출되면, XMLHttpRequest의 readyState 프로퍼티가 1로 지정되어야 한다.
  • send 메소드가 전송되고 HTTP 응답 헤더가 수신되면, XMLHttpRequest의 readyState 프로퍼티가 2로 지정되어야 한다.
  • HTTP 응답 내용이 전송되기 시작하면, XMLHttpRequest의 readyState 프로퍼티가 3로 지정되어야 한다.
  • HTTP 응답 내용 전송이 완료되면, XMLHttpRequest의 readyState 프로퍼티가 4로 지정되어야 한다.


  • After the open method has been invoked successfully, the readyState property of the XMLHttpRequest object should be assigned a value of 1.
  • After the send method has been invoked and the HTTP response headers have been received, the readyState property of the XMLHttpRequest object should be assigned a value of 2.
  • Once the HTTP response content begins to load, the readyState property of the XMLHttpRequest object should be assigned a value of 3.
  • Once the HTTP response content has finished loading, the readyState property of the XMLHttpRequest object should be assigned a value of 4.


리스너는 리스너가 정의된 후 일어난 상태변화에만 반응한다. 상태 1, 2을 감지려면 open 메소드가 호출되기 전에 리스너를 정의해야 한다. open 메소드는 반드시 send 메소드가 호출되기 전에 호출되어야 한다.


The listener will only respond to state changes which occur after the listener is defined. To detect states 1 and 2, the listener must be defined before the open method is invoked. The open method must be invoked before the send method is invoked.


xmlhttp.onreadystatechange = function() {

    if (xmlhttp.readyState === 4){

        alert(xmlhttp.readyState);

    }

};


xmlhttp.open('GET', 'somepage.xml', true);


// 서버에 ajax 목적으로 이 호출이 이루어짐을 알림. 

// jQuery/Prototype/Dojo 등의 대부분의 라이브러리가 이를 수행함. 

// Tells server that this call is made for ajax purposes.

//  Most libraries like jQuery/Prototype/Dojo do this

xmlhttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); 

            

xmlhttp.send(null); // No data need to send along with the request.


abort 메소드


이 메소드는 XMLHttpRequest 객체의 readyState 가 아직 4로 되지 않았다면 요청을 취소한다. abort 메소드는 콜백핸들러가 비동기 요청으로 호출되지 않았다는 것을 보증한다.??


This method aborts the request if the readyState of the XMLHttpRequest object has not yet become 4. The abort method ensures that the callback handler does not get invoked in an asynchronous request.


abort ()


일부 AJAX 라이브러리는 잘못된 요청이나 중복 요청을 취소하기 위해 abort 메소드를 사용한다.


Some AJAX libraries use the abort method to cancel potential duplicate or out-of-order requests.


HTTP 응답


XMLHttpRequest의 send 메소드가 성공적으로 호출이 완료된 후, 서버 응답이 적법한 XML이고, 서버에서 송신한 Content-type 헤더를 브라우저가 XML의 인터넷 미디어 타입으로 이해할 수 있을 경우, XMLHttpRequest 객체의 responseXML 프로퍼티는 DOM 문서 객체를 담고있게 된다. 또 다른 프로퍼티인 responseText에는 서버 응답을 (XML로 이해할 수 있든 아니든) 일반 문자열로 담고 있게 된다.


After a successful and completed call to the send method of the XMLHttpRequest, if the server response was valid XML and the Content-Type header sent by the server is understood by the user agent as an Internet media type for XML, the responseXML property of the XMLHttpRequest object will contain a DOM document object. Another property, responseText will contain the response of the server in plain text by a conforming user agent, regardless of whether or not it was understood as XML.


교차 도메인 요청(Cross-domain requests)


인터넷 초기에 자바스크립트를 사용하여, 어떤 웹사이트의 정보를 평판이 나쁜 사이트의 정보로 교체함으로써 사용자 보안을 무력화시키는 게 가능하다는 것이 발견되었다. 따라서 모든 최신 브라우저는 cross-site scripting과 같은 공격을 막을 수 있는 동일출처정책(same-origin policy)을 구현하고 있다. XMLHttpRequest 데이터도 이러한 보안 정책의 영향을 받지만, 의도적으로 이러한 제한을 우회하는 방법이 필요하다. 예를 들어 여러개의 서브도메인을 합법적으로 사용할 경우,  foo.example.com 에서 생성한 페이지로부터 bar.example.com에 있는 정보를 XMLHttpRequest로 호출하려는 시도는 실패하게 된다.


In the early development of the World Wide Web, it was found possible to breach users' security by the use of JavaScript to exchange information from one web site with that from another less reputable one. All modern browsers therefore implement a same origin policy that prevents many such attacks, such as cross-site scripting. XMLHttpRequest data is subject to this security policy, but sometimes web developers want intentionally to circumvent its restrictions. This is sometimes due to the legitimate use of subdomains as, for example, making an XMLHttpRequest from a page created by foo.example.com for information from bar.example.com will normally fail.


이러한 보안 기능을 우회하기 위한 방법은 JSONP, 교차출처 자원공유(CORS: Cross-Origin Resource Sharing)를 사용하거나, Flash/Silverlight 등의 플러그인을 사용하는 등 여러가지가 있다. 교차출처 XMLHttpRequest는 W3C XMLHttpRequest Level2 사양에 정의되어 있으며, 모든 최신 브라우저(모바일 및 데이크탑)가 지원한다. 


Various alternatives exist to circumvent this security feature, including using JSONP, Cross-Origin Resource Sharing (CORS) or alternatives with plugins such as Flash or Silverlight. Cross-origin XMLHttpRequest is specified in W3C's XMLHttpRequest Level 2 specification[32] and it is supported by all modern browsers (desktop and mobile).


Internet Explorer는 버전 10까지 CORS를 구현하지 않았다. 이전의 8 및 9 버전에서는 XDomainRequest API를 통해 비슷한 기능을 제공하였다. 이 API는 요청 헤더 설정거부, 쿠키의 생략을 비롯한 여러가지 제한이 있다. 아울러 GET 및 POST 요청만 지원되었다. 하지만 대부분의 서버측 프레임워크에서는 Content-type 요청헤더가 "application/x-www-urlencoded"가 필요함에도 XDomainRequest의 POST 메소드는 "text/plain" 만 허용하기 때문에 거의 활용하기 힘들었다. 

Internet Explorer did not implement CORS until version 10. The two previous versions (8 and 9) offered similar functionality through the XDomainRequest API. This API has several restrictions, including but not limited to: denial of setting custom request headers and omission of cookies. Further, only the GET and POST request methods are supported. In practice, the POST method is barely useful, because the only allowed value for the Content-Type request header is "text/plain", while many server-side frameworks require "application/x-www-urlencoded" to function properly.


====

Posted by 푸른하늘 푸른하늘이

댓글을 달아 주세요

기타/웹 2.02014. 1. 21. 17:09

이 문서는 영문 위키피디아 문서를 번역한 것입니다.

====


컴퓨팅에서 동일출처정책은 자바스크립트(Javascript)와 같은 브라우저측 프로그래밍 언어에서 중요한 보안 개념이다. 이 정책에 의하면, 동일한 사이트에서 나온 페이지에서 돌아가는 스크립트는 별다른 제한 없이 서로의 DOM을 접근할 수 있지만, 다른 사이트에 있는 DOM은 접근이 허용되지 않는다. 여기에서 동일한 사이트란 scheme, 호스트이름 및 포트번호를 조합한 것이다. 동일출처정책은 XMLHttpRequest 및 robots.txt에도 적용된다.


In computing, the same-origin policy is an important security concept for a number of browser-side programming languages, such as JavaScript. The policy permits scripts running on pages originating from the same site – a combination of scheme, hostname, and port number – to access each other's DOM with no specific restrictions, but prevents access to DOM on different sites. Same-origin policy also applies to XMLHttpRequest and to robots.txt.


이 메카니즘은 입증된 사용자 세션(authenticated user sessions)을 유지하기 위해 HTTP 쿠키에 널리 의존하는 현대적 웹 어플리케이션에서 특별히 중요하다. HTTP 쿠키 정보에 근거하여, 서버가 민감한 정보를 제공하거나 상태가 변경되는 액션을 취하기 때문이다. 데이터의 기밀이나 일관성을 유지하기 위해서는, 클라이언트측에서 관계없는 사이트로부터 제공된 콘텐트를 엄격하게 분리해야 한다.


This mechanism bears a particular significance for modern web applications that extensively depend on HTTP cookies to maintain authenticated user sessions, as servers act based on the HTTP cookie information to reveal sensitive information or take state-changing actions. A strict separation between content provided by unrelated sites must be maintained on the client side to prevent the loss of data confidentiality or integrity.


역사(History)


동일출처정책의 개념은 1995년 넷스케이프사의 내비게이터2로 거슬러 올라간다. 원래의 개념과 거의 비슷한 개념이 현재 모든 브라우저에 사용되고 있으며, 얼추 호환성있는 다른 웹 스크립팅 언어 (아도비 플래시 혹은 아도비 아크로뱃)이나, 직접적인 DOM 처리와는 완전히 다른 XMLHttpRequest 같은 메카니즘에도 확장 적용되고 있다. 


The concept of same-origin policy dates back to Netscape Navigator 2 in 1995. Close derivatives of the original design are used in all current browsers[citation needed] and are often extended to define roughly compatible security boundaries for other web scripting languages, such as Adobe Flash or Adobe Acrobat, or for mechanisms other than direct DOM manipulation, such as XMLHttpRequest.


출처결정원칙(Origin determination rules)


URI의 출처를 계산하는데 사용되는 알고리듬은 RFC 6454  4절에 정의되어 있다. 절대 URI의 출처는 {protocol, host, port} 등 세가지로 구성된다. URI가 naming authority(RFC 3986, Section 3.2 참고)와 같은 계층적 요소를 사용하지 않거나, URI가 절대 URI가 아니라면, globally unique identifier 가 사용된다. 이 모든 값이 정확하게 같을 경우에만 두개의 자원이 동일출처로 간주된다. 


The algorithm used to calculate the "origin" of a URI is specified in RFC 6454, Section 4. For absolute URIs, the origin is the triple {protocol, host, port}. If the URI does not use a hierarchical element as a naming authority (see RFC 3986, Section 3.2) or if the URI is not an absolute URI, then a globally unique identifier is used. Two resources are considered to be of the same origin if and only if all these values are exactly the same. 


아래는 "http://www.example.com/dir/page.html" 에 대하여 체크를 했을 때의 개략적인 전형적 결과를 보여주는 표이다.


To illustrate, the following table gives an overview of typical outcomes for checks against the URL "http://www.example.com/dir/page.html".


비교대상 URL결과Reason
httpː//www.example.com/dir/page2.htmlSuccess프로토콜과 호스트 동일
httpː//www.example.com/dir2/other.htmlSuccess프로토콜과 호스트 동일
httpː//username:password@www.example.com
/dir2/other.html
Success프로토콜과 호스트 동일
httpː//www.example.com:81/dir/other.htmlFailure포트가 다름
https://www.example.com/dir/other.htmlFailure프로토콜이 다름
http://en.example.com/dir/other.htmlFailure호스트가 다름
http://example.com/dir/other.htmlFailure호스트가 다름(정확히 일치해야)
http://v2.www.example.com/dir/other.htmlFailure호스트가 다름(정확히 일치해야)
httpː//www.example.com:80/dir/other.htmlDon't use서버에 따라 다름


다른 브라우저와는 달리 IE는 출처를 결정할 때 포트는 사용하지 않는다. 대신 Security Zone을 사용한다.


Unlike other browsers, Internet Explorer does not include the port in the calculation of the origin, using the Security Zone in its place.


동일출처정책의 회피(Relaxing the same-origin policy)


경우에 따라서는 동일출처 정책은 너무 제한이 많아서 서브-도메인이 많은 대규모 웹사이타 같은 경우 문제를 일으키고 있다. 아래는 이를 회피하는 네가지 기법이다.


In some circumstances the same-origin policy is too restrictive, posing problems for large websites that use multiple subdomains. Here are four techniques for relaxing it:


document.domain 프로퍼티를 사용하는 방법


두개의 윈도(혹은 프레임)에 도메인을 같은 값으로 설정하는 스크립트가 있을 경우, 동일출처정책은 이 두개의 윈도간에는 완화되어, 한 윈도가 다른 윈도와 상호작용할 수 있다. 예를 들어, orders.example.com 과catalog.example.com 에서 불러온 문서에 포함된 스크립트가 document.domain 프로퍼티를 "example.com"으로 설정하면, 이에 따라 문서가 동일한 출처인 것처럼 보이게 되어, 한 문서가 다른 문서의 프로퍼티를 읽을 수 있게 된다. 이것은 내부 표현에 저장된 포트가 null로 표시될 수 있기 때문에 항상 잘 작동하는 것은 아니다. 예를 들어, document.domain을 갱신함으로써, example.com:80 이 example.com 으로 바뀌게 된다는 것이다. 포트번호가 없으면 80으로 취급되지 않을 수도 있으므로(브라우저에 따라 다름), 브라우저에 따라 성공할 수도 실패할 수도 있다. 


If two windows (or frames) contain scripts that set domain to the same value, the same-origin policy is relaxed for these two windows, and each window can interact with the other. For example, cooperating scripts in documents loaded from orders.example.com and catalog.example.com might set their document.domain properties to “example.com”, thereby making the documents appear to have the same origin and enabling each document to read properties of the other. This might not always work as the port stored in the internal representation can become marked as null. In other words example.com port 80 will become example.com port null because we update document.domain . Port null might not be treated as 80 ( depending on your browser ) and hence might fail or succeed depending on your browser.


Cross-Origin Resource Sharing(CORS


동일출처 정책을 회피하는 두번째 기법은 출처 자원공유(CORS : Cross-Origin Resource Sharing)라는 이름으로 표준화되었다. 이 표준초안에는 HTTP에 새로운 Origin 요청 헤더와 새로운 Access-Control-Allow-Origin 응답 헤더를 추가하였다. 이를 통해 서버에서는 파일 요청을 허용한 명시적인 출처(origin) 리스트에 헤더를 사용하거나 혹은 와일드카드(*)를 사용하여 모든 사이트가 파일을 요청할 수 있도록 허용할 수 있다. 파이어폭스 3.5와 사파리 4와 같은 브라우저는 이러한 새로운 헤더를 사용하여 XMLHttpRequest를 사용한 동일출처를 벗어난 HTTP 요청을 허용하고 있다. CORS가 아니었다면 동일출처정책에 의해 금지되었을 것이다.


The second technique for relaxing the same-origin policy is being standardized under the name Cross-Origin Resource Sharing. This draft standard extends HTTP with a new Origin request header and a new Access-Control-Allow-Origin response header. It allows servers to use a header to explicitly list origins that may request a file or to use a wildcard and allow a file to be requested by any site. Browsers such as Firefox 3.5 and Safari 4 use this new header to allow the cross-origin HTTP requests with XMLHttpRequest that would otherwise have been forbidden by the same-origin policy.


크로스 다큐먼트 메시징(Cross-document messaging)

또다른 새로운 기법인 크로스 다큐먼트 메시징을 사용하면 어떤 페이지에 있는 스크립트로부터 다른 페이지에 있는 스크립트에 (스크립트 출처에 관계없이) 텍스트 메시지를 전달할 수 있다. Window 객체에 있는 postMessage() 메소드를 호출하면 해당 윈도에 비동기적으로 "onmessage" 이벤트를 발생시켜, 사용자 정의 이벤트핸들러를 부를 수 있다. 한 페이지에 있는 스크립트는 여전히 다른 페이지에 있는 메소드나 변수에 직접적으로 접근할 수는 없으나, 메시지 전달 기법을 통해 안전하게 통신할 수 있다.


Another new technique, cross-document messaging allows a script from one page to pass textual messages to a script on another page regardless of the script origins. Calling the postMessage() method on a Window object asynchronously fires an "onmessage" event in that window, triggering any user-defined event handlers. A script in one page still cannot directly access methods or variables in the other page, but they can communicate safely through this message-passing technique.


JSONP

JSONP를 사용하면 다른 도메인으로부터 JSON 데이터를 받을 수 있다. 그 페이지에 다른 도메인으로부터 JSON 응답을 받을 수 있는 <script> 요소를 추가하면 된다.


JSONP allows a page to receive JSON data from a different domain by adding a <script> element to the page which loads a JSON response from a different domain.


극단적 조건 및 예외(Corner cases and exceptions)


동일출처 점검 및 관련 메카니즘의 행태는 여러가지 극단적 조건에서는 잘 정의되지 않는다. 예를 들어 URL에 명확하게 정의된 호스트이름이나 포트가 없는 (file:, data:, 등) 가상 프로토콜(pseudo-protocol)등에서 이런 문제가 발생한다. 이는 역사적으로 여러가지 보안문제를 발생시켰다. 예를 들어 로칼에 저장된 HTML 파일이 디스크에 있는 모든 파일에 접근할 수 있다던가, 인터넷상의 모든 사이트와 통신할 수 있는 등 일반적으로 바람직하지 않는 기능 등이 문제가 되었다.


The behavior of same-origin checks and related mechanisms is not well-defined in a number of corner cases, such as for pseudo-protocols that do not have a clearly defined host name or port associated with their URLs (file:, data:, etc.). This historically caused a fair number of security problems, such as the generally undesirable ability of any locally stored HTML file to access all other files on the disk, or communicate with any site on the Internet.


아울러 자바스크립트 이전의 많은 합법적 크로스도메인 작업에 대해서는 동일출처 점검에 해당되지 않는다. 이러한 예로서, 다른 도메인으로부터 스크립트를 불러오는 것이나, 폼을 POST 하는 것 등이 있다.


In addition, many legacy cross-domain operations predating JavaScript are not subjected to same-origin checks; one such example is the ability to include scripts across domains, or submit POST forms.


마지막으로 DNS 리바인딩이나 서버측 프록시와 같은 일부 공격을 통하면 호스트이름 점검을 부분적으로 망가뜨림으로써, 원래의 진짜 출처가 아닌 주소를 통해서 가짜 웹페이지가 직접 해당사이트를 조작할 수 있게된다. 이러한 공격의 효과는 아주 특별할 시나리오에 한한다. 브라우저의 입장에서는 공격자의 사이트와 통신한다고 믿고 있으며, 따라서 제3의 쿠키나 다른 민감한 정보를 공격자에게 노출시키지 않기 때문이다.


Lastly, certain types of attacks, such as DNS rebinding or server-side proxies, permit the host name check to be partly subverted, and make it possible for rogue web pages to directly interact with sites through addresses other than their "true", canonical origin. The impact of such attacks is limited to very specific scenarios, since the browser still believes that it is interacting with the attacker's site, and therefore does not disclose third-party cookies or other sensitive information to the attacker.


차선책(Workarounds)


개발자들이 잘 통제된 상황내에서 동일출처정책을 우회할 수 있도록 하려면, fragment identifier나 window.name 프로퍼티를 사용하는 등 여러가지 편법(hacks)을 사용하여 다른 도메인에 있는 문서간에 데이터를 전달해 왔다. HTML5 표준에서는 이 방법들이 공식화되었다. 바로 postMessage 인터페이스로서 최신 브라우저에서만 사용가능하다. JSONP도 역시 다른 도메인에 Ajax와 비슷한 호출을 활성화시키기 위해 사용될 수 있다.


To enable developers to, in a controlled manner, circumvent the same-origin policy, a number of "hacks" such as using the fragment identifier or the window.name property have been used to pass data between documents residing in different domains. With the HTML5 standard, a method was formalized for this: the postMessage interface,[5][6] which is only available on recent browsers.[7] JSONP can also be used to enable Ajax-like calls to other domains.


=====

제가 기술에 대해 잘 모르기 때문에 공부할 요량으로 번역을 했으나, 그렇기 때문에 정확하지 않을 수 있습니다. 혹시 잘못 이해한 부분이 있다면 댓글로 남겨주시면 감사하겠습니다.


민, 푸른하늘

Posted by 푸른하늘 푸른하늘이

댓글을 달아 주세요

  1. 손님

    좋은 번역 글 감사합니다~ 개념 정리하는데 많은 도움이 되었어요.

    2015.09.22 18:50 [ ADDR : EDIT/ DEL : REPLY ]