Reprint: browser cross-domain Introduction

Transfer: https://my.oschina.net/u/4203303/blog/3102954

First, what is the cross-domain?

JavaScript for security considerations do homologous policy restrictions , does not allow cross-domain access to other resources. Typically the cross-domain request is successful, the browser will reject the results returned by the server in response.

1. For security reasons what aspects?

The purpose of the same-origin policy is to prevent a malicious website to steal user data information impersonate the user to do some operations. Homologous restriction only increases the cost of the attack. Without JavaScript homologous restrictions:

(1) CSRF attacks

(2) XSS attack

2. What is homologous?

Domain name, protocol, port are the same. For example, http://www.example.com/dir/page.htmlthe URL is the protocol http://, the domain name www.example.com, port 80(default port can be omitted)

3. What restrictions do?

(1) cross-origin communication between the Window object: Unable to read Cookie, LocalStorage, IndexDB and access to DOM, but by the following tags can access resources across domains:

<img src="URL">
<link href="URL"> <script src="URL"> <iframe src="URL"> <form action="URL" method="get/post"> First name: <input type="text" name="fname"><br> Last name: <input type="text" name="lname"><br> <input type="submit" value="提交"> </form>

Further, if the non-homologous web, now allowed to get the other windows / pages through JavaScript scripts windownine four properties and methods of an object.

  • window.closed
  • window.frames
  • window.length
  • window.location
  • window.opener
  • window.parent
  • window.self
  • window.top
  • window.window
  • window.blur()
  • window.close()
  • window.focus()
  • window.postMessage()

Wherein only window.locationbe read (in the case of non-homologous, only allows the calling location.replacemethod and writing location.hrefproperties), the other eight are all read-only.

Room (3) Client Server: Browser AJAX request reject response.

4. how to be a cross-domain?

As opposed http://store.company.com/dir/page.htmlexample of the detection of homologous:

URL result the reason
http://store.company.com/dir2/other.html success  Only different path
http://store.company.com/dir/inner/another.html success  Only different path
https://store.company.com/secure.html failure Different protocols (https and http)
http://store.company.com:81/dir/etc.html failure Different ports (http: // 80 is the default)
http://news.company.com/dir/other.html failure Different domain name (news and store)

Note: the domain name corresponding ip can not successfully access

Second, how to solve cross-domain restrictions?

Cross-source communication between objects 1.Window

(1) If the page just two different secondary domain, a domain name identical

① browser settings allows document.domainsharing of Cookie, get the DOM.

/****A网页:http://t1.example.com/a.html*/

document.domain = 'example.com';
//设置cookie
document.cookie = "test1=hello"; /****B网页:http://t2.example.com/b.html,设置相同的document.domain*/ document.domain = 'example.com'; //访问A网页的cookie console.log(document.cookie); /*注意:A 和 B 两个网页都需要设置document.domain属性,才能达到同源的目的。因为设置document.domain的同时,会把端口重置为null,因此如果只设置一个网页的document.domain,会导致两个网址的端口不同,还是达不到同源的目的*/

② In addition, the server can also be set when Cookie, Cookie specify the domain name belongs to a domain name, the second / third-level domains do not do any settings, you can read the Cookie

Set-Cookie: key=value; domain=.example.com; path=/

Disadvantages: This method applies only to shared Cookie and iframe window, LocalStorage and IndexDB this way can not be shared across domains

(2) For completely different website source, cross-domain communication problems can be solved by following three windows:

① segment identifier (URL of #the back part of the number)

Just change the url fragment identifier, the page will not refresh the parent window can put information, write fragment identifier of the child window.

//****父窗口把要共享的信息添加到子窗口url的#后

var src = originURL + '#' + data;
document.getElementById('myIFrame').src = src; //****子窗口监听窗口变化 window.onhashchange = ()=>{ //获取url的#后的数据 var data= window.location.hash; } //子窗口也可以通过这种方式向父窗口共享信息 parent.location.href= target + "#" + hash;

②window.name

The browser window window.nameattributes, whether homologous as long as in the same window, a front page this attribute is set, after a web page can read it, and a large capacity, can be placed very long string.


//****子窗口:http://child.url.com/xxx.html,将信息写入window.name属性:

window.name = data;

location = 'http://parent.url.com/other.html';//接着,子窗口跳回一个与父窗口同域的网址。



//****父窗口:http://parent.url.com/xxx.html,先打开不同源的子窗口网页: var iframe = document.createElement('iframe'); iframe.id='myFrame'; iframe.src = 'http://child.url.com/xxx.html';//iframe可以跨域加载资源 document.body.appendChild(iframe); //然后,父窗口就可以读取子窗口的window.name了。 var data = document.getElementById('myFrame').contentWindow.name;

Disadvantages: must listen to the child window window.namechange the properties, the impact of web performance.

③window.postMessage

HTML5 In order to solve communication problems between the cross source Window object (e.g.: pages between it and the pop-up window, or between the iframe is embedded therein, see in particular: https://www.w3cschool.cn/fetch_api/fetch_api- lx142x8t.html ), introduced - cross-document communication API. This API is windowthe object of a new window.postMessagemethod that allows cross-window communication, regardless of whether the two homologous windows.

/*语法:otherWindow.postMessage(message, targetOrigin, [transfer]);
message:要发送的数据信息
targetOrigin:接收消息的窗口的源(origin),即"协议 + 域名 + 端口"。也可以设为*,表示不限制域名,向所有窗口发送。
*/


//****父窗口"http://aaa.com"向子窗口"http://bbb.com"发消息

var popup = window.open('http://bbb.com', 'title'); popup.postMessage('Hello World!', 'http://bbb.com'); //****子窗口通过message事件,监听发送者的消息 window.addEventListener('message', function(event) { console.log(event.source);//发送源自的窗口:popup (子窗口可以通过event.source属性引用父窗口,然后发送消息) console.log(event.origin);//发送源自的域:"http://aaa.com"(通过event.origin验证发送者,分派事件的origin属性的值不受调用窗口中document.domain的当前值的影响) console.log(event.data);//消息内容:'Hello World!' },false);

safe question

① If you do not want to receive message from other sites, please do not add any event listeners for message events, this is a totally foolproof way to avoid security problems 

② If you do want to receive message from other sites, always use the identity of the origin and source attributes verify the sender, so as not to receive a malicious message sent by a malicious Web site. 

③ When you use postMessage to send data to another window, always specify the precise target origin, and not * to avoid being the middle of a malicious Web site to intercept information postMessage sent.

Detail View: https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage

2.AJAX

Homologous policy, AJAX request can only be issued to homologous URL, otherwise an error. Three solutions:

(1) set up a proxy server

Homologous browser requests the server, and then by the latter request an external service

(2) JSONP

JSONP is a common method of communication across the source server and client, simple to apply, good compatibility.

Fundamental:

① add a page <script>element, a request to the server script code runs directly as this is not same-origin policy restrictions, you can cross-domain requests.

② After the server receives a request, a string of splicing, the data on the function name JSON, as a string ( bar({...}))

String ③ client server will return as code analysis, since the browser that this is the <script>contents of the script tag request. In this case, as long as the client defines the bar()function, the function can be in vivo, to get JSON data returned by the server.

//请求的脚本网址有一个callback参数(?callback=bar),用来告诉服务器,客户端的回调函数名称(bar)
<script src="http://api.foo.com?callback=bar"></script>


//定义bar()函数,在该函数体内,拿到服务器返回的 JSON 数据 function foo(data) { console.log('服务器返回:' + data.id); }; //服务器收到这个请求以后,会将数据放在回调函数的参数位置返回。 foo({ 'ip': '8.8.8.8' });

Disadvantages: can only get request

(3)WebSocket

WebSocket protocol is based on TCP network protocol, substituted bidirectional communication technology as a transport layer by HTTP - allow the server actively sends information to the client. Using ws://(non-encrypted) and wss://(encrypted) as the protocol prefix.

① The WebSocket server request header Originfield (represented by: from which domain request), it is determined whether to permit the current communication

② If the domain name in the white list, the server will respond, so there is no limit homology

//websocket请求头(摘自网络)

GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat Sec-WebSocket-Version: 13 Origin: http://example.com //判断为白名单后,服务端做出回应 HTTP/1.1 101 Switching Protocols Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk= Sec-WebSocket-Protocol: chat

(3) HEARTS

CORS is a cross-origin resource sharing (Cross-Origin Resource Sharing) acronym, is a W3C standard, is the fundamental solution to cross-source AJAX request.

  • Compared to only send JSONP GETrequest, CORS allows any type of request.
  • CORS need to support both browser and server, the communication is the key to achieve CORS server. CORS long as the server implements the interface, you can cross-domain communication.
  • CORS request into two categories, dividing the reason is that the form has been cross-domain request in history. Is a simple request form request, the browser followed the traditional approach, not the behavior of complex, developers might otherwise turn to use the form, to circumvent the restrictions of CORS. For non-simple request, the browser will adopt a new approach:

① a simple request: simple HTTP method (head, get, post) with simple HTTP header information (Accept, Accept-Language, Content -Language, Last-Event-ID, Content-Type: is limited to three values application/x-www-form-urlencoded, multipart/form-data, text/plain) combination.

  • For simple requests, the browser sees the cross-domain AJAX request is a simple request, sent directly CORS request, automatically header information in to add a Originfield.
  • If the Origin specified source, not within the permissible range, the server returns a normal HTTP response header information does not contain Access-Control-Allow-Origin field. After the browser receives in order to throw an error, it is the XMLHttpRequest onerror callback function to capture. Note that this error code is not recognized by the state, because the HTTP response status code might be 200.
  • If the domain name specified in the Origin permitted range, the server in response header Access-Control-Allow-Origin request header field contains the Originvalue of the field.
//***请求头:
GET /cors HTTP/1.1
Origin: http://api.bob.com  /*表示请求来自哪个域(协议 + 域名 + 端口)。服务器根据这个值,决定是否同意这次请求*/
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...



//****如果Origin指定的域名在许可范围内,服务端响应头之中,会多出几个头信息字段,有三个与 CORS 请求相关的字段,都以Access-Control-开头。 Access-Control-Allow-Origin: http://api.bob.com /*该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。同时,必须在 AJAX 请求中打开withCredentials属性才起作用*/ Access-Control-Allow-Credentials: true/*可选,布尔值。设为true,即表示服务器明确许可,浏览器可以把 Cookie 包含在请求中,一起发给服务器。*/ Access-Control-Expose-Headers: FooBar Content-Type: text/html; charset=utf-8 

② non-simple request: non-simple request is a request to the server that the special requirements, such as: request method is PUTor DELETE, or Content-Typetype field is application/json.

  • Non-simple request CORS request, before the official communication, increase an HTTP query request, called "preflight" request (preflight).
  • Server receives a "pre-screening" after the request, examined Origin, Access-Control-Request-Methodand Access-Control-Request-Headersafter field, acknowledge allow cross-origin requests, we can respond.
  • If the server is denied "preflight" request, it returns a normal HTTP response, but no related CORS header field, or made it clear that the request does not meet the conditions.
  • Once the server through a "preflight" request, after each time the browser requests a normal CORS, as it related to a simple request, there will be a Originheader field. Server response, but also will have a Access-Control-Allow-Originheader field.
//****JavaScript脚本:
var url = 'http://api.alice.com/cors';
var xhr = new XMLHttpRequest(); xhr.open('PUT', url, true); xhr.setRequestHeader('X-Custom-Header', 'value'); xhr.send(); //****“预检”请求头 OPTIONS /cors HTTP/1.1 /*“预检”请求用的请求方法是OPTIONS,表示这个请求是用来询问的*/ Origin: http://api.bob.com /*表示请求来自哪个源*/ Access-Control-Request-Method: PUT /*该字段是必须的,用来列出浏览器的 CORS 请求会用到哪些 HTTP 方法,本例是PUT*/ Access-Control-Request-Headers: X-Custom-Header /*该字段是一个逗号分隔的字符串,指定浏览器 CORS 请求会额外发送的头信息字段,本例是X-Custom-Header*/ Host: api.alice.com Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0... ①//****服务器否定了“预检”请求的响应头: OPTIONS http://api.bob.com HTTP/1.1 Status: 200 Access-Control-Allow-Origin: https://notyourdomain.com/*明确不包括发出请求的http://api.bob.com*/ Access-Control-Allow-Method: POST //****浏览器发现服务器不同意预检请求,触发一个错误,被XMLHttpRequest对象的onerror回调函数捕获。控制台报错信息: XMLHttpRequest cannot load http://api.alice.com. Origin http://api.bob.com is not allowed by Access-Control-Allow-Origin. ②//****服务器允许了“预检”请求的回应头: HTTP/1.1 200 OK Date: Mon, 01 Dec 2008 01:15:39 GMT Server: Apache/2.0.61 (Unix) Access-Control-Allow-Origin: http://api.bob.com /*表示http://api.bob.com可以请求数据。该字段也可以设为星号,表示同意任意跨源请求。*/ Access-Control-Allow-Methods: GET, POST, PUT /*该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次“预检”请求。*/ Access-Control-Allow-Headers: X-Custom-Header /*如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在“预检”中请求的字段。*/ Content-Type: text/html; charset=utf-8 Content-Encoding: gzip Content-Length: 0 Keep-Alive: timeout=2, max=100 Connection: Keep-Alive Content-Type: text/plain Access-Control-Max-Age: 1728000 /*该字段可选,用来指定本次预检请求的有效期,单位为秒。这里有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。*/ //****“预检”请求通过之后,浏览器的会再发一个正常 CORS 请求: PUT /cors HTTP/1.1 Origin: http://api.bob.com Host: api.alice.com X-Custom-Header: value Accept-Language: en-US Connection: keep-alive User-Agent: Mozilla/5.0... //****然后,服务器正常的回应: Access-Control-Allow-Origin: http://api.bob.com Content-Type: text/html; charset=utf-8

Cons: compatibility is not good (> ie10)

 

 

 

 

Referring specifically to: https://wangdoc.com/javascript/bom/cors.html

Detail View: https://wangdoc.com/javascript/bom/same-origin.html

Other Links: https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage

Guess you like

Origin www.cnblogs.com/yaohuimo/p/11525324.html