What is cross-domain?
Cross-domain refers to a document or script in one domain trying to request a resource in another domain. Cross-domain is defined broadly here.
In a broad sense, cross-domain:
1.) Resource jump: A link, redirect, form submission 2.<link>,<script>,<img>,<frame>3.) Script request: AJAX request initiated by JS, cross-domain operation of DOM and JS objects, etcCopy the code
In fact, what we usually mean by cross-domain is narrowly defined, a class of request scenarios that are restricted by the browser’s same-origin policy.
What is the same origin policy? The Same Origin Policy (SOP) is a convention introduced by Netscape into the browser in 1995. It is the core and most basic security function of the browser. Without the Same Origin policy, the browser is vulnerable to XSS and CSFR attacks. Same-origin means that the protocol, domain name, and port are the same. Even if two different domain names point to the same IP address, they are not same-origin.
The same origin policy restricts the following behaviors:
1.Cookie, LocalStorage, and IndexDB cannot be read2.DOM and Js objects are not available3.AJAX requests cannot be sentCopy the code
Common cross-domain scenarios
URL indicates whether communication is allowedhttp://www.domain.com/a.js
http://www.domain.com/b.js Same domain name, different files or paths allowed
http://www.domain.com/lab/c.js
http://www.domain.com:8000/a.js
http://www.domain.com/b.js The same domain name, different ports are not allowed
http://www.domain.com/a.js
https://www.domain.com/b.js Same domain name, different protocols do not allow
http://www.domain.com/a.js
http://192.168.4.12/b. Js domain names cannot correspond to the same IP address
http://www.domain.com/a.js
http://x.domain.com/b.js The primary domain is the same, but the subdomain is different
http://domain.com/c.js
http://www.domain1.com/a.js
http://www.domain2.com/b.js different domain names are not allowedCopy the code
Cross-domain solutions
Hash + iframe 4. Window. name + iframe 5. PostMessage 6. Cross-domain resource sharing (CORS) 7, Cross-domain nginx proxy 8, cross-domain NodeJS middleware proxy 9, cross-domain WebSocket protocol
First, cross domains through JSONP
Usually, in order to reduce the load of the Web server, we separate static resources such as JS, CSS and IMG to another server with an independent domain name, and then load static resources from different domain names in the HTML page through corresponding tags, which are allowed by the browser. Based on this principle, we can dynamically create script. Request a reference url to achieve cross-domain communication.
1.) Native implementation:
<script>
var script = document.createElement('script');
script.type = 'text/javascript';
// Pass the parameter and specify the callback execution function as onBack
script.src = 'http://www.domain2.com:8080/login?user=admin&callback=onBack';
document.head.appendChild(script);
// The callback executes the function
function onBack(res) {
alert(JSON.stringify(res));
}
</script>Copy the code
The server returns the following (executes the global function when it returns) :
onBack({"status": true."user": "admin"})Copy the code
2. Jquery Ajax:
$.ajax({
url: 'http://www.domain2.com:8080/login'.type: 'get'.dataType: 'jsonp'.// The request is jSONP
jsonpCallback: "onBack".// Custom callback function name
data: {}
});Copy the code
3.) the vue. Js:
this.$http.jsonp('http://www.domain2.com:8080/login', {
params: {},
jsonp: 'onBack'
}).then((res) = > {
console.log(res);
})Copy the code
Examples of back-end Node.js code:
var querystring = require('querystring');
var http = require('http');
var server = http.createServer();
server.on('request'.function(req, res) {
var params = qs.parse(req.url.split('? ') [1]);
var fn = params.callback;
// jsonp returns Settings
res.writeHead(200, { 'Content-Type': 'text/javascript' });
res.write(fn + '(' + JSON.stringify(params) + ') ');
res.end();
});
server.listen('8080');
console.log('Server is running at port 8080... ');Copy the code
Disadvantages of JSONP: Only one get request can be implemented.
Document.domain + iframe cross domain
This solution applies only to cross-domain scenarios where the primary domain is the same and the subdomains are different.
Implementation principle: two pages through JS forced document.domain as the base of the primary domain, to achieve the same domain.
1.) parent window :(www.domain.com/a.html)
<iframe id="iframe" src="http://child.domain.com/b.html"></iframe>
<script>
document.domain = 'domain.com';
var user = 'admin';
</script>Copy the code
2.) sub-window :(child.domain.com/b.html)
<script>
document.domain = 'domain.com';
// Get the variables in the parent window
alert('get js data from parent ---> ' + window.parent.user);
</script>Copy the code
Location. hash + iframe cross-domain
Implementation principle: A wants to communicate with B across domains, which is achieved through the middle page C. Three pages, different fields use iframe location.hash to transfer values, the same fields directly js access to communicate.
A domain: A.html -> B domain: B.html -> A domain: C.HTML, A and B different domain can only hash value one-way communication, B and C are also different domain can only one-way communication, but C and A are the same domain, so C can access all objects on A page through parent. Parent.
1.) A.HTML (www.domain1.com/a.html)
<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
<script>
var iframe = document.getElementById('iframe');
// Pass hash values to B.html
setTimeout(function() {
iframe.src = iframe.src + '#user=admin';
}, 1000);
// callback methods open to homologous C.HTML
function onCallback(res) {
alert('data from c.html ---> ' + res);
}
</script>Copy the code
2.) B.HTML (www.domain2.com/b.html)
<iframe id="iframe" src="http://www.domain1.com/c.html" style="display:none;"></iframe>
<script>
var iframe = document.getElementById('iframe');
// listen for hash values from A.html and pass them to C.HTML
window.onhashchange = function () {
iframe.src = iframe.src + location.hash;
};
</script>Copy the code
3.) C. HTML (www.domain1.com/c.html)
<script>
// Listen for hash values from B.html
window.onhashchange = function () {
// Return the result by manipulating the javascript callback of the same domain A.html
window.parent.parent.onCallback('hello: ' + location.hash.replace('#user='.' '));
};
</script>Copy the code
Window. Name + iframe cross domain
The window.name attribute is unique in that the name value persists across different pages (and even different domain names) and supports very long name values (2MB).
1.) A.HTML (www.domain1.com/a.html)
var proxy = function(url, callback) {
var state = 0;
var iframe = document.createElement('iframe');
// Load the cross-domain page
iframe.src = url;
// The onload event fires twice, the first time the cross-domain page is loaded and the data is stored in window.name
iframe.onload = function() {
if (state === 1) {
// After the second onload(syndomain proxy page) succeeds, the data in syndomain window.name is read
callback(iframe.contentWindow.name);
destoryFrame();
} else if (state === 0) {
// After the first onload succeeds, switch to the same-domain proxy page
iframe.contentWindow.location = 'http://www.domain1.com/proxy.html';
state = 1; }};document.body.appendChild(iframe);
// After the data is retrieved, the iframe is destroyed to free memory; This also ensures security (not accessed by other fields frame JS)
function destoryFrame() {
iframe.contentWindow.document.write(' ');
iframe.contentWindow.close();
document.body.removeChild(iframe); }};// Request cross-domain B page data
proxy('http://www.domain2.com/b.html'.function(data){
alert(data);
});Copy the code
2.) proxy. HTML: (www.domain1.com/proxy… Intermediate proxy page, same domain as A.HTML, content is empty.
3.) B.HTML (www.domain2.com/b.html)
<script>
window.name = 'This is domain2 data! ';
</script>Copy the code
Summary: The SRC attribute of iframe is used to pass the data from the outfield to the local region. The cross-domain data is passed from the outfield to the local region by the window.name of iframe. This is a neat way to circumvent the browser’s cross-domain access restrictions, but it’s also a secure operation.
PostMessage is cross-domain
PostMessage is an API in HTML5 XMLHttpRequest Level 2, and is one of the few window properties that can operate across domains. It can be used to solve the following problems: A.) data transfer between the page and the new window it opens b.) message transfer between multiple Windows c.) message transfer between the page and nested iframe d.) cross-domain data transfer for the three scenarios above
Usage: The postMessage(data, Origin) method takes two arguments data: the HTML5 specification supports any primitive type or replicable object, but some browsers only support strings, so it’s best to serialize the argument with json.stringify (). Origin: protocol + host + port number. The value can also be set to “*”, which indicates that it can be sent to any window. If you want to specify the origin of the current window, set it to “/”.
1.) A.HTML (www.domain1.com/a.html)
<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;"></iframe>
<script>
var iframe = document.getElementById('iframe');
iframe.onload = function() {
var data = {
name: 'aym'
};
// Send cross-domain data to domain2
iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.domain2.com');
};
// Accept data from domain2
window.addEventListener('message'.function(e) {
alert('data from domain2 ---> ' + e.data);
}, false);
</script>Copy the code
2.) B.HTML (www.domain2.com/b.html)
<script>
// Receive data from domain1
window.addEventListener('message'.function(e) {
alert('data from domain1 ---> ' + e.data);
var data = JSON.parse(e.data);
if (data) {
data.number = 16;
// Send it back to domain1
window.parent.postMessage(JSON.stringify(data), 'http://www.domain1.com'); }},false);
</script>Copy the code
Vi. Cross-domain Resource Sharing (CORS)
Common cross-domain request: Only access-Control-allow-origin is required on the server. Cookie request: Both the front and back ends need to set fields. In addition, note that the cookie carried is the cookie of the domain where the cross-domain request interface resides, not the current page. Currently, all browsers support this functionality (IE8+ : IE8/9 requires the use of XDomainRequest objects to support CORS), and CORS has become a mainstream cross-domain solution.
1. Front-end Settings:
1.) Native Ajax
// Set whether cookies are included in the front end
xhr.withCredentials = true;Copy the code
Sample code:
var xhr = new XMLHttpRequest(); // Ie8/9 must be window.xdomainRequest compatible
// Set whether cookies are included in the front end
xhr.withCredentials = true;
xhr.open('post'.'http://www.domain2.com:8080/login'.true);
xhr.setRequestHeader('Content-Type'.'application/x-www-form-urlencoded');
xhr.send('user=admin');
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) { alert(xhr.responseText); }};Copy the code
2.) the jQuery ajax
$.ajax({
...
xhrFields: {
withCredentials: true // Set whether cookies are included in the front end
},
crossDomain: true.// The request header contains additional cross-domain information, but does not contain cookies. });Copy the code
3.) The VUE framework adds the following code to the Vue-Resource wrapped Ajax component:
Vue.http.options.credentials = trueCopy the code
2. Server Settings:
If the Settings are successful, the console of the front-end browser will not display cross-domain error messages; otherwise, the Settings are not successful.
1.) Java background:
/ * * import packages: import javax.mail. Servlet. HTTP. HttpServletResponse; * Defined in interface parameters: HttpServletResponse Response */
response.setHeader("Access-Control-Allow-Origin"."http://www.domain1.com"); // Write full (protocol + domain + port)
response.setHeader("Access-Control-Allow-Credentials"."true");Copy the code
2.) Nodejs
var http = require('http');
var server = http.createServer();
var qs = require('querystring');
server.on('request'.function(req, res) {
var postData = ' ';
// Data block received
req.addListener('data'.function(chunk) {
postData += chunk;
});
// Data is received
req.addListener('end'.function() {
postData = qs.parse(postData);
// Cross-domain background Settings
res.writeHead(200, {
'Access-Control-Allow-Credentials': 'true'.// The backend allows sending cookies
'Access-Control-Allow-Origin': 'http://www.domain1.com'.// Allowed domain (protocol + domain name + port)
'Set-Cookie': 'l=a123456; Path=/; Domain=www.domain2.com; HttpOnly' // HttpOnly: The script cannot read cookies
});
res.write(JSON.stringify(postData));
res.end();
});
});
server.listen('8080');
console.log('Server is running at port 8080... ');Copy the code
Nginx proxies cross domains
1, nginx configuration to resolve iconfont cross-domain
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 / { add_header Access-Control-Allow-Origin *;
}Copy the code
2. Nginx reverse proxy interfaces cross domains
Cross-domain principle: The same Origin policy is a security policy of the browser, not a part of the HTTP protocol. The server invokes the HTTP interface only using THE HTTP protocol, and does not execute JS scripts. There is no need for the same origin policy, so there is no crossing problem.
Nginx configure a proxy server (domain name and domain1 the same, different port) as a jumper, reverse proxy access to domain2 interface, and can incidentally modify the cookie in the domain information, convenient for the current domain cookie writing, cross-domain login.
Nginx configuration:
# proxy server
server {
listen 81;
server_name www.domain1.com;
location / {
proxy_pass http://www.domain2.com:8080; # Reverse proxy
proxy_cookie_domain www.domain2.com www.domain1.com; # change the domain name in cookie
index index.html index.htm;
# When accessing Nignx using middleware proxy interfaces such as Webpack-dev-server, there is no browser participation, so there is no source restriction, the following cross-domain configuration can not be enabled
add_header Access-Control-Allow-Origin http://www.domain1.com; # If the current end is cross-domain only without cookies, the value can be *
add_header Access-Control-Allow-Credentials true; }}Copy the code
1.) Front-end code examples:
var xhr = new XMLHttpRequest();
// Front-end switch: whether the browser reads and writes cookies
xhr.withCredentials = true;
// Access the proxy server in nginx
xhr.open('get'.'http://www.domain1.com:81/?user=admin'.true);
xhr.send();Copy the code
2.) Nodejs
var http = require('http');
var server = http.createServer();
var qs = require('querystring');
server.on('request'.function(req, res) {
var params = qs.parse(req.url.substring(2));
// Write cookies to the front desk
res.writeHead(200, {
'Set-Cookie': 'l=a123456; Path=/; Domain=www.domain2.com; HttpOnly' // HttpOnly: the script cannot read
});
res.write(JSON.stringify(params));
res.end();
});
server.listen('8080');
console.log('Server is running at port 8080... ');Copy the code
Nodejs middleware proxy across domains
Node middleware to achieve cross-domain proxy, the principle is roughly the same as Nginx, are by starting a proxy server, data forwarding.
1. Cross-domain of non-VUE framework (twice cross-domain)
Build a proxy server with Node + Express + HTTP-proxy-middleware.
1.) Front-end code examples:
var xhr = new XMLHttpRequest();
// Front-end switch: whether the browser reads and writes cookies
xhr.withCredentials = true;
// Access the HTTP-proxy-Middleware proxy server
xhr.open('get'.'http://www.domain1.com:3000/login?user=admin'.true);
xhr.send();Copy the code
2.) Middleware server
var express = require('express');
var proxy = require('http-proxy-middleware');
var app = express();
app.use('/', proxy({
// Proxy cross-domain target interface
target: 'http://www.domain2.com:8080'.changeOrigin: true.// Modify the response header information to cross-domain and allow cookies
onProxyRes: function(proxyRes, req, res) {
res.header('Access-Control-Allow-Origin'.'http://www.domain1.com');
res.header('Access-Control-Allow-Credentials'.'true');
},
// Change the cookie domain name in the response information
cookieDomainRewrite: 'www.domain1.com' // The value can be false, indicating no change
}));
app.listen(3000);
console.log('Proxy server is listen at port 3000... ');Copy the code
3. Nginx: Nginx
2. Cross-domain of VUE framework (once cross-domain)
Cross domain using node + Webpack + webpack-dev-server agent interface. In the development environment, since the Vue rendering service and the interface proxy service are the same as Webpack-dev-server, there is no need to set headers cross-domain information between the page and proxy interface.
Webpack.config.js part configuration:
module.exports = {
entry: {},
module: {},... devServer: {historyApiFallback: true.proxy: [{
context: '/login'.target: 'http://www.domain2.com:8080'.// Proxy cross-domain target interface
changeOrigin: true.cookieDomainRewrite: 'www.domain1.com' // The value can be false, indicating no change}].noInfo: true}}Copy the code
9. WebSocket protocol is cross-domain
WebSocket Protocol is a new protocol for HTML5. It implements full duplex communication between browser and server, and allows cross-domain communication. It is a good implementation of server push technology. The native WebSocket API is not very convenient to use. We use socket. IO, which encapsulates the WebSocket interface well, provides a simpler, flexible interface, and provides backward compatibility for browsers that do not support WebSocket.
1.) Front-end code:
<div>User input:<input type="text"></div>
<script src="./socket.io.js"></script>
<script>
var socket = io('http://www.domain2.com:8080');
// The connection was successfully processed
socket.on('connect'.function() {
// Listen for server messages
socket.on('message'.function(msg) {
console.log('data from server: ---> ' + msg);
});
// The listener server is closed
socket.on('disconnect'.function() {
console.log('Server socket has closed.');
});
});
document.getElementsByTagName('input') [0].onblur = function() {
socket.send(this.value);
};
</script>Copy the code
Nodejs socket background:
var http = require('http');
var socket = require('socket.io');
// Start the HTTP service
var server = http.createServer(function(req, res) {
res.writeHead(200, {
'Content-type': 'text/html'
});
res.end();
});
server.listen('8080');
console.log('Server is running at port 8080... ');
// Listen for socket connections
socket.listen(server).on('connection'.function(client) {
// Receive information
client.on('message'.function(msg) {
client.send('hello:' + msg);
console.log('data from client: ---> ' + msg);
});
// Disconnect processing
client.on('disconnect'.function() {
console.log('Client socket has closed.');
});
});Copy the code