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:
Access-Control-Allow-Credentials
为true
Represents 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
- Request must be set
withCredentials
Otherwise, even if the server requires itCookie
And the browser won’t handle it. Access-Control-Allow-Origin
For 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:
-
Data transfer between the page and the new window it opens
-
Messaging between multiple Windows
-
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.