preface

What is cross-domain, and why is there cross-domain? What is the cross-domain solution? What is commonly used? How does it work?

What is cross-domain

Cross-domain refers to requesting resources from one domain name to another domain name.

Strictly speaking, any difference in domain name, protocol, or port is considered cross-domain.


Cross-domain scenario

It doesn’t matter how similar the following looks, it’s all cross-domain.

Primary domain different

http://www.chrome.cn/index.html
http://www.chomper.cn/server.php
Copy the code

Different subdomains

http://abc.chomper.cn/index.html 
http://def.chomper.cn/server.php
Copy the code

Different ports

http://www.chomper.cn:8080/index.html
http://www.chomper.cn/server.php  
Copy the code

Agreement is different

https://www.chomper.cn/index.html
http://www.chomper.cn/server.php
Copy the code

The localhost call to 127.0.0.1 is also cross-domain

Non-cross-domain scenarios

The following protocols, domain names, and ports are the same.

http://www.chomper.cn/index.html 
http://www.chomper.cn/server.php
Copy the code

Cross-domain prompt

The following error is received when you cross domains


Why cross-domains

To ensure network security, browsers set the same origin policy, specifying that only domain names, ports, and protocols are the same.

How to resolve cross-domain

Cross-domain resource sharing

Cross-domain resource sharing (CORS) is a mechanism, specifically a W3C standard, that overcomes the same origin policy. CORS is currently the mainstream cross-domain solution.

The entire resource sharing process, without the participation of developers, is automatically completed by the browser. For developers, there is no difference between homologous and non-homologous asynchronous communication, and the code is exactly the same.

As soon as the browser discovers that the asynchronous request is across the source, it automatically adds some additional header information, so the key to resource sharing is the server. As long as the server implements the CORS interface, cross-source communication is possible.

Before sending a cross-domain request, the browser determines whether it is a simple request or a non-simple request, because the browser handles the two requests differently.

A simple request

If it is a simple request, the server program is executed before the browser determines whether it is cross-domain.

The browser will add an Origin field (protocol + domain + port) to the header, and the server will decide whether to approve the request based on Origin.

If not, the server will return a normal HTTP response, and the browser will throw an error if it finds that the response header does not contain the Access-Control-Allow-Origin field.

Access-Control-Allow-Origin: http://api.bob.com
Content-Type: text/html; charset=utf-8
Copy the code

Note that this error cannot be identified by the status code, because the status code for the HTTP response might be 200.

If the following conditions are met, it is a simple request. Otherwise, it is a non-simple request.

In case 1, the following request methods are simple requests, and other requests are non-simple requests.

  • GET
  • POST
  • HEAD

In case two, the header information cannot exceed the following fields.

  • Accept
  • Accept-Language
  • Content-Language
  • Content-type (Additional restrictions need to be noted)
  • DPR
  • Downlink
  • Save-Data
  • Viewport-Width
  • Width

In case three, the value of the Content-Type is limited to one of the following (for example, application/ JSON is not a simple request).

  • text/plain
  • multipart/form-data
  • application/x-www-form-urlencoded

Non-simple request

In other cases, it is not a simple request.

If the request is not simple, the browser sends an OPTIONS request to perform pre-check. The pre-check request is called a “pre-check request”. The server sends a real request with real data only after it successfully responds to the pre-check request.

The browser automatically adds the Origin field when sending the OPTIONS request, and also includes two special fields.

Access-control-request-method (which HTTP methods will be used)Access-control-request-headers (a comma-separated string specifying additional header fields to be sent)Copy the code

Allow-origin allow-methods allow-headers Headers = allow-origin allow-methods allow-headers = allow-origin allow-methods allow-headers To respond to cross-domain requests with precheck.

Note: A server can set access-Control-max-age to tell the browser not to send a precheck request again for a certain amount of time, but this does not work if the browser disables caching.

When the browser receives the OPTIONS response, it will compare whether the method in the real request is one of the allow-methods values returned, as well as origin and head.

Note: If it passes, the browser continues to send the real request to the server, otherwise it will report a precheck error.



Server-side processing

Because of the cross-domain problem, the server needs to be set to agree to any cross-source request:

Access-Control-Allow-Origin: *

Allow-methods and Allow-headers are only useful when responding to options requests. Allow-origin is only useful when responding to options requests and real requests. Both must contain the source to cross domains.

Although non-simple requests can be supported by setting the response header and response mode, the client should not be allowed to send non-simple requests unless it is absolutely necessary. Non-simple requests cause twice as much stress on the server as simple requests.

Finally, use JSONP when using Internet Explorer <=9, Opera<12, or Firefox<3.5, or older browsers.

About the cookie

CORS requests do not send cookies by default. In order to transmit cookies, three conditions must be met:

  1. Access-Control-Allow-CredentialstrueRepresents that the server agrees to sendCookie.
// How to set up native XML
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
// Axios setting
axios.defaults.withCredentials = true;
Copy the code
  1. Request must be setwithCredentialsOtherwise, even if the server requires itCookieAnd the browser won’t handle it.
  2. Access-Control-Allow-OriginFor the*, specify a specific domain name consistent with the requested page.

The browser doesn’t see options

In the new Chrome, if you send complex requests, you don’t see options requests. Here you can set Chrome ://flags/# out-of-of-blink-cors to disbale and restart the browser. Options requests are visible for non-simple requests.

JSONP

Since script tags are allowed by browsers to load static resource files from different domains, JSONP exploits this “criminal vulnerability” to cross domains.

While this approach is useful, the biggest drawback is that it only supports the GET method. If you want to use the full REST interface, use CORS or some other proxy method.

Dynamically create script tags

let script = document.createElement('script');

script.src = 'http://www.chomper.cn/login?username=chomper&callback=callback';

document.body.appendChild(script);
 function callback(res) {  console.log(res); } Copy the code

Plain JS example

<script type="text/javascript">
  window.jsonpCallback = function(res) {
    console.log(res);
  };
</script>
<script  src="http://localhost:8080/api/jsonp? msg=hello&cb=jsonpCallback"  type="text/javascript"> </script> Copy the code

Nginx agents cross domains

Nginx reverse proxy


In order to solve the cross-domain problem, let the browser first send the request to the current domain name of nginx, then nginx determines the URL, through the match to find the request is dynamic, and finally forward the request to the server interface, bypassing the browser, so there will be no cross-domain problem.

server {
    listen  8080;
    server_name  localhost;
    location / {
      root html;
 index index.html index.htm;  } // Generally, you only need to add the proxy configuration information here location /api/ { rewrite ^.+/api/? $/ (. *)The $1 break;  include uwsgi_params; Proxy_pass http://10.10.10.10:1000/; } } Copy the code

Nginx configuration resolves iconFONT across domains

Browser cross-domain access js, CSS, and img conventional static resources are the same-origin policy permission, but iconfont font file (eot | otf | the vera.ttf | woff | SVG) exception, at this time in nginx server to add the following configuration static resources.

location ~* \.(eot|otf|ttf|woff|svg)$ {
  add_header  Access-Control-Allow-Origin *;
}
Copy the code

Vue-cli reverse proxy

In fact, the idea is the same as the above nginx reverse proxy, first intercepts the request in the middle layer, in the middle layer to send the request, without passing through the browser, naturally bypassing the same origin policy.

  devServer: {
        open: true, // Whether the browser page is automatically displayed        host: "localhost".        port: '8081'.        https: false. hotOnly: false. proxy: {  '/api': {  target: 'http://localhost:5000'// Address of the API server ws: true, // Proxy WebSockets changeOrigin: true// Virtual sites need to manage OriginPathRewrite: {// Rewrite the path for example'/api/aaa/ccc'Rewritten as'/aaa/ccc'  '^/api': ' '  }  }  },  } Copy the code

Note: The interface fields to be matched are set as variables in the development environment. The URL is set when using AXIOS request, and variable API is uniformly added before THE URL to realize the request matching proxy.

postMessage

This is an API from H5, which is used to send messages to external Windows, so we can circumvent the same origin policy in this way.

What it can do:

  1. Data transfer between the page and the new window it opens

  2. Messaging between multiple Windows

  3. Page with nested IFrame message delivery

otherWindow.postMessage(message,targetOrigin);
Copy the code

OtherWindow is the target window to which the Message is to be sent, Message is the Message to be sent, the type is String, Object(IE8 and IE9 do not support Obj), targetOrigin is to limit the scope of the Message, Use the asterisk * if you don’t limit it

Detailed usage at https://developer.mozilla.org/zh-CN/docs/Web/API/Window/postMessage

WebSocket

WebSocket does not use HTTP per se, so there are no cross-domain restrictions, but I haven’t used them so I won’t describe them here.

document.domain + Iframe

This cross-domain method requires the same primary domain name, for example, a.test.com and b.test.com. The two primary domain names are both test.com. However, this method cannot be used if the primary domain names are different.

// a.test.com
<body>
  helloa
  <iframe
    src="http://b.test.com/b.html"
 frameborder="0"  onload="load()"  id="frame"  ></iframe>  <script>  document.domain = "test.com";  function load() {  console.log(frame.contentWindow.a);  }  </script> </body> Copy the code
// b.test.com
<body>
  hellob
  <script>
    document.domain = "test.com";
 var a = 100;  </script> </body> Copy the code

Disable the same-origin security policy

To facilitate local development, we can turn off the same origin policy in the browser.

Need to remind everybody, general situation must not easily use this way.

mac

~/Downloads/chrome-data This directory can be customized.

/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary  --disable-web-security --user-data-dir=~/Downloads/chrome-data  
Copy the code

windows

Find your installation directory.\Google\Chrome\Application\chrome.exe --disable-web-security --user-data-dir=xxxx
Copy the code

Reference documentation

https://mp.weixin.qq.com/s/vuIjDVQ0MzT6SRhVhlfswQ

https://juejin.cn/post/6844903521163182088#heading-14

https://www.jianshu.com/p/ebd498cc3c52

https://www.jianshu.com/p/c68d404a3ab9

At the end

If this article has helped you, please like it and follow it, search for Manta Fish in the Ocean and join our technology group to learn and discuss and explore the frontier together.