Detailed browser cross-domain

1. What is cross-domain?

For security reasons, JavaScript is restricted by the same- origin policy , which does not allow cross-domain access to other resources. Usually, after a successful cross-domain request, the browser will refuse to respond to the result returned by the server.

1. What are the safety considerations?

The purpose of the same-origin policy is to prevent malicious websites from stealing user data and impersonating users to do some operations. The same-origin restriction just increases the attack cost. Without JavaScript same-origin restrictions:

(1) CSRF attack

(2) XSS attack

2. What is homology?

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

3. What restrictions are made?

(1) Cross-source communication between Window objects: Cookie cannot be read ( cookies only distinguish domain names, not ports, so when processing cookies, you must first add a port mark to the cookie to distinguish it. I would like to thank the Taoist friends who corrected me in the comment area ), LocalStorage , IndexDB and Get DOM, but you can access resources across domains through the following tags:

<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>

In addition, if it is a non-homologous web page, it is currently allowed to obtain windownine properties and four methods of objects of other windows/web pages through JavaScript scripts.

  • 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()

Among them, only window.locationare readable and writable (in the case of non-same origin, only calling location.replacemethods and writing location.hrefproperties are allowed), and the other eight are all read-only.

(3) Between the client and the server: the browser refuses to accept the response of the AJAX request.

4. How is it considered cross-domain?

An example of relative http://store.company.com/dir/page.htmlhomology detection is as follows:

URL result reason
http://store.company.com/dir2/other.html success  only the path is different
http://store.company.com/dir/inner/another.html success  only the path is different
https://store.company.com/secure.html fail Different protocols (https and http)
http://store.company.com:81/dir/etc.html fail Different port (http://80 is the default)
http://news.company.com/dir/other.html fail Different domains ( news and store )

Note: The domain name and its corresponding ip cannot be accessed successfully either.

2. How to solve cross-domain restrictions?

1. Cross-origin communication between Window objects

(1) If the two web pages are only different in the second-level domain name, the first-level domain name is the same

① The browser allows document.domainyou to get the DOM by setting a shared cookie.

/****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 specify the domain name of the cookie as the first-level domain name when setting the cookie, and the second/third-level domain name can read the cookie without any settings.

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

Disadvantages: This method is only suitable for sharing cookies and iframe windows, LocalStorage and IndexDB cannot be shared across domains through this method

(2) For websites with completely different origins, the communication problem of cross-domain windows can be solved by the following three methods:

① Fragment identifier ( #the part after the number of the URL)

Just change the fragment identifier of the url, the page will not be refreshed again, the parent window can write the information into the 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 property of the browser window window.name, as long as it is in the same window, regardless of whether it is of the same origin, the previous web page sets this property, and the latter web page can read it, and the capacity is large, and a very long string can be placed.


//****子窗口: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: You must monitor window.namechanges in child window properties, affecting web page performance.

③window.postMessage

HTML5 in order to solve the problem of cross-origin communication between Window objects (for example: between the page and its popup window, or between the iframe embedded in it, see: https://www.w3cschool.cn/fetch_api/fetch_api- lx142x8t.html ), Introduced - Cross-Document Communication API. This API windowadds a window.postMessagemethod to the object that allows cross-window communication, regardless of whether the two windows are of the same origin.

/*语法: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 don't want to receive messages from other websites, please don't add any event listeners for message events , this is a completely foolproof way to avoid security issues 

② If you really want to receive messages from other websites, please always use the origin and source attributes to verify the sender's identity , so as not to receive malicious information sent by malicious websites. 

③ When you use postMessage to send data to other windows, always specify the exact target origin, not *, so as to avoid the information sent by postMessage being intercepted by malicious websites .

For details, see: https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage

2.AJAX

The same-origin policy stipulates that AJAX requests can only be sent to the same-origin URL, otherwise an error will be reported. Three solutions:

(1) Set up a server proxy

The browser requests the same-origin server, which in turn requests the external service

(2) JSONP

JSONP is a common method for cross-source communication between the server and the client. It is simple and applicable and has good compatibility.

Fundamental:

①Add an <script>element to the web page, request a script from the server, and run it directly as code, which is not restricted by the same-origin policy and can be requested across domains.

② After the server receives the request, it splices a string, puts the JSON data in the function name, and returns it as a string ( bar({...}))

③ The client will parse the string returned by the server as code, because the browser thinks that this is <script>the script content requested by the tag. At this time, as long as the client defines a bar()function, it can get the JSON data returned by the server in the function body.

//请求的脚本网址有一个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'
});

Disadvantage: only get request

(3)WebSocket

The WebSocket protocol is a TCP-based network protocol that replaces the two-way communication technology that uses HTTP as the transport layer - allowing the server to actively send information to the client. Use ws://(non-encrypted) and wss://(encrypted) as protocol prefixes.

Origin①The server judges whether to allow this communication according to the field of the WebSocket request header (indicating: which domain name the request originates from)

②If the domain name is in the whitelist, the server will respond, so there is no same-origin restriction

//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) COURSES

CORS is the abbreviation of Cross-Origin Resource Sharing (Cross-Origin Resource Sharing), which is a W3C standard and the fundamental solution for cross-origin AJAX requests.

  • Compared with JSONP, which can only send GETrequests, CORS allows any type of request.
  • CORS needs to be supported by both the browser and the server. The key to CORS communication is the server. Cross-domain communication is possible as long as the server implements the CORS interface.
  • CORS requests are divided into two categories, the reason for the division is that forms have historically been able to make requests across domains. A simple request is a form request. The browser follows the traditional processing method and does not complicate the behavior. Otherwise, the developer may turn to the form to avoid the limitation of CORS. For non-simple requests, the browser will take a new approach:

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

  • The browser finds that the cross-domain AJAX request is a simple request, directly sends a CORS request, and automatically adds a Originfield to the header information.
  • If the origin specified by Origin is not within the scope of permission, the server will return a normal HTTP response, the header information Access-Control-Allow-Origin does not contain Origin. After receiving it, the browser throws an error, which is caught by the onerror callback function of XMLHttpRequest. Note that this kind of error cannot be identified by the status code, as the HTTP response status code may be 200.
  • If the domain name specified by Origin is within the permitted range, the Access-Control-Allow-Origin field in the server response header contains Originthe value of the field in the request header.

//****JavaScript脚本:
var url = 'http://api.alice.com/cors';
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.withCredentials = true;/*在 AJAX 请求中打开withCredentials属性,从而向服务器发送 Cookies。但是,如果服务器端的响应中未携带 Access-Control-Allow-Credentials: true ,浏览器将不会把响应内容返回给请求的发送者。*/
xhr.send();



//***请求头:
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字段的值(如果服务端指定了具体的Origin域名,则响应头中的 Vary 字段的值必须包含 “Origin”,告诉客户端:服务器对不同的源站返回不同的内容),对于不需要携带身份凭证的请求(请求头没有携带cookie信息),服务器可以指定该字段的值为一个*,表示接受任意域名的请求。*/
Access-Control-Allow-Credentials: true /*可选字段。表示服务器明确许可浏览器可以把 Cookie 包含在请求中,一起发给服务器。但,须 AJAX 请求中打开withCredentials属性才起作用*/
Access-Control-Expose-Headers: FooBar /*在跨域访问时,XMLHttpRequest对象的getResponseHeader()方法只能拿到一些最基本的响应头,Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma,如果要访问其他头,则需要服务器设置本响应头,把允许浏览器访问的头放入白名单*/
Content-Type: text/html; charset=utf-8

②Non-simple request: A non-simple request is a request that puts special requirements on the server, such as: the request method is PUTor DELETE, or Content-Typethe type of the field is application/json.

  • For CORS requests that are not simple requests, an HTTP query request will be added before the formal communication, which is called a "preflight" request. The use of "preflight request" can prevent cross-domain requests from having unexpected effects on the server's user data.
  • After the server receives the "preflight" request, after checking the Originand fields, Access-Control-Request-Methodand Access-Control-Request-Headersconfirming that the cross-origin request is allowed, it can respond.
  • If the server rejects the "preflight" request, it will return a normal HTTP response without any CORS-related header fields, or explicitly indicate that the request is not eligible.
  • Once the server passes the "preflight" request, every subsequent normal CORS request from the browser will be the same as a simple request, and there will be a Originheader field. The server's response will also 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

Disadvantage: poor compatibility (>ie10)

 

 

 

 

For details, see: https://wangdoc.com/javascript/bom/cors.html

For details, see: https://wangdoc.com/javascript/bom/same-origin.html

Other related links: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage , https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS

 

{{o.name}}
{{m.name}}

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=324085313&siteId=291194637