First, what is cross-domain

In a broad sense, cross-domain:


<link>, <script>, <img>, <frame> and other DOM tags, as well as background: URL (), @font-face() and other file external links. Js-initiated Ajax requests, DOM and JS object cross-domain operations, 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. This is when the browser cannot execute scripts from other sites. Is a security restriction that browsers impose on JavaScript.

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:

  • Cookie, LocalStorage, and IndexDB cannot be read

  • DOM and JS objects cannot be retrieved

  • The Ajax request could not be sent

Pay special attention to two points: first, if protocols and ports cause cross-domain problems, the “foreground” is powerless. Second: in terms of cross-domain problems, domains are only identified by “the head of the URL” without trying to determine whether the same IP address corresponds to two domains or whether two domains are on the same IP address.

2. Common cross-domain scenarios


URL that whether to allow communication http://www.domain.com/a.js http://www.domain.com/b.js the same domain name, Different file or path to allow 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 Do not allow the http://www.domain.com/a.js https://www.domain.com/b.js the same domain name, Different protocols Do not allow the http://www.domain.com/a.js http://192.168.4.12/b.js domain names and domain name corresponding to the same IP is not allowed to http://www.domain.com/a.js http://x.domain.com/b.js Same primary domain, Different subdomains Do not allow the different domain name http://domain.com/c.js http://www.domain1.com/a.js http://www.domain2.com/b.js Don't allowCopy the code

3. Common cross-domain solutions

Cross domains via JSONP

In order to reduce the load of the Web server, static resources such as JS, CSS and IMG are separated to another server with an independent domain name, and static resources are loaded 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.

JSONP consists of two parts: callback functions and data.

The callback function is the function that is called to be placed on the current page when the response arrives.

The data is the JSONP data passed into the callback function, which is the argument to the callback function





Jsonp takes advantage of the non-cross-domain nature of script tags by appending the name of the callback function to the parameter of the SRC URL. Function doSomething(data) {// handle data} var script = document.createElement("script"); script.src = "http://www.b.com/b.html?callback=doSomething"; document.body.appendChild(script); // 1. Generate a script tag, append it to the body, and request the server // 2. The server generates a data-containing function doSomething({"a", "1"}) // 3 based on the callback argument. The doSomething(data) function is declared in the page. $. Ajax ({url:'http://192.168.9.5/jsonp_test1.jsp', dataType:" jSONp ", jSONp :"jsonpcallback", success:function(data){ var $ul = $("<ul></ul>"); $.each(data,function(i,v){ $("<li/>").text(v["id"] + " " + v["name"]).appendTo($ul) }); $("#res").append($ul); }}); C# [HttpGet] public ActionResult getSurvey_Contact(String contact_id, String survey_id) {var callback = Request.QueryString["callback"]; / / get the callback function name var contactColl = MyMongoDb. CurrentDB. GetCollection (" Survey_Contact "); if (contact_id == null) contact_id = String.Empty; var doc = contactColl.FindAs<BsonDocument>(Query.And(Query.EQ("contact_id", contact_id), Query.EQ("Survey_Id", survey_id))).FirstOrDefault(); if (doc == null) doc = new BsonDocument(); FormateJSON(new[] { doc }); var answerColl = MyMongoDb.CurrentDB.GetCollection("Survey_Answers"); var answerDocs = answerColl.FindAs<BsonDocument>(Query.And(Query.EQ("contact_id", contact_id), Query.EQ("survey_id", survey_id))).ToArray(); FormateJSON(answerDocs); doc.Set("answers", new BsonArray(answerDocs)); var result = new ContentResult(); result.ContentEncoding = System.Text.Encoding.UTF8; result.ContentType = "application/json"; //Regex reg = new Regex("ObjectId\\(([a-z0-9])\\)"); if (String.IsNullOrWhiteSpace(callback)) { result.Content = doc.ToJson(); return result; } else { result.Content = callback + "(" + doc.ToJson() + ");" ; Callback (data) return result; }}Copy the code





// Jquery $.Jsonp or $. Ajax Jsonp has nothing to do with Ajax. In fact, JSONP takes advantage of the fact that script tags have no cross-domain constraints: It is not restricted by the same origin policy as Ajax requests implemented by XMLHttpRequest objects; It is more compatible, runs in older browsers and does not require XMLHttpRequest or ActiveX support; After the request is complete, the result can be returned by calling callback. Disadvantages of JSONP: It only supports GET requests and does not support other types of HTTP requests such as POST. It only supports cross-domain HTTP requests and does not solve the problem of how to make JavaScript calls between two pages in different domains.Copy the code


Document.domain + iframe addresses 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.

Example 1

1.) the parent window: (http://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








<script> document.domain = 'domain.com'; Alert ('get js data from parent --> '+ window.parent. User); </script>Copy the code


Example 2





This method applies to the same primary domain but different subdomains, such as http://www.a.com and http://b.a.com, if the two domains have a.html and B.html, a.html document.domain = "a.com"; var iframe = document.createElement("iframe"); iframe.src = "http://b.a.com/b.html"; document.body.appendChild(iframe); iframe.onload = function() { console.log(iframe.contentWindow....) ; } b.html document.domain = "a.com"; Note: Document.domain needs to be set to its own parent field or higher, and the primary field must be the same.Copy the code


Location. hash + iframe resolve 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.h HTML: (http://www.domain1.com/a.html) –

Copy the code


<iframe id="iframe" src="http://www.domain2.com/b.html" style="display:none;" ></iframe> <script> var iframe = document.getElementById('iframe'); SetTimeout (function() {iframe.src = iframe.src + '#user=admin'; }, 1000); Function onCallback(res) {alert('data from c.html --> '+ res); } </script>Copy the code








<iframe id="iframe" src="http://www.domain1.com/c.html" style="display:none;" ></iframe> <script> var iframe = document.getElementById('iframe'); Onhashchange = function () {ifame. SRC = ifame. SRC + location.hash; }; </script>Copy the code











<script> // Listen for window.onhashchange = function () { The results back to the window. The parent. The parent. OnCallback (' hello, '+ location. Hash. Replace (' # user =', ')); };Copy the code


Window. name + iframe resolve cross-domain

The window.name property sets or returns a string that holds the window name. The window.name attribute is unique in that the name value persists after loading on different pages (and even different domain names) and can support a very long name value (2MB).


var proxy = function(url, callback) { var state = 0; var iframe = document.createElement('iframe'); // Load the cross-domain page iframe.src = url; Name ifame. Onload = function() {if (state === 1) {// If (state === 1) {// If (state === 1) {// If (state === 1) { Read with domain window. The name of the callback data (iframe. ContentWindow. Name); destoryFrame(); } else if (state === 0) { Switch to the same domain agent 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; It also ensures safety frame js (not by other domain access) 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: (http://www.domain1.com/proxy… Intermediate proxy page, same domain as A.HTML, content is empty.

3.) b.h HTML: (http://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 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.h HTML: (http://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' }; / / to send cross domain data domain2 iframe. ContentWindow. PostMessage (JSON. Stringify (data), 'http://www.domain2.com'); }; Window. addEventListener('message', function(e) {alert('data from domain2 --> '+ e.data); }, false); </script>Copy the code








Windows. addEventListener('message', function(e) {alert('data from domain1 --> '+ e.ata); var data = JSON.parse(e.data); if (data) { data.number = 16; / / send back again after processing domain1 window. The parent. PostMessage (JSON. Stringify (data), 'http://www.domain1.com'); } }, false); </script>Copy the code


Cross-domain Resource Sharing (CORS)

For common cross-domain requests, only access-Control-allow-origin is required on the server. This parameter is not required on the front end. If cookie is required, access-Control-allow-origin is required on both the front and back ends.

Note that due to the restriction of the same-origin policy, the cookie read is the cookie of the domain where the cross-domain request interface resides, not the current page. Nginx reverse proxy sets proxy_cookie_domain and cookieDomainRewrite (NodeJs).

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


// The front end sets whether to bring cookie xhr.withCredentials = true;Copy the code








var xhr = new XMLHttpRequest(); // Ie8/9 requires window.XDomainRequest compatibility // The front end is set to whether the cookie 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








$.ajax({ ... XhrFields: {withCredentials: true}, crossDomain: true, // Will make the request header contain additional information across domains, but not cookies... });Copy the code











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; HttpServletResponse Response */ / allow cross-domain access domain name: SetHeader (" access-Control-allow-origin ", "http://www.domain1.com"); response.setHeader(" access-Control-allow-origin ", "http://www.domain1.com"); // Allow front-end authentication cookies: When this item is enabled, the domain name cannot be '*', and the specific domain name must be specified. Otherwise, the browser displays response. SetHeader (" access-Control-allow-credentials ", "true");Copy the code








var http = require('http'); var server = http.createServer(); var qs = require('querystring'); server.on('request', function(req, res) { var postData = ''; Req. addListener('data', function(chunk) {postData += chunk; }); Req.addlistener ('end', function() {postData = qs.parse(postData); // Set res.writeHead(200, {' access-control-allow-credentials ': 'true', // back end allows sending Cookie 'access-Control-allow-origin ': 'http://www.domain1.com', // allowed domain (protocol + domain + port) /* * Set cookies to domain2 instead of domain1, because the back end can not write cookies across domains (nginx reverse proxy can do this), */ 'set-cookie ': 'l=a123456; */' set-cookie ': 'l=a123456; Path=/; Domain=www.domain2.com; HttpOnly' // HttpOnly prevents javascript from reading cookies}); res.write(JSON.stringify(postData)); res.end(); }); }); server.listen('8080'); console.log('Server is running at port 8080... ');Copy the code


Nginx agents 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:

Copy the code








#proxy 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 cookie domain name index index.html index.htm; # When accessing Nignx with middleware proxy interface such as Webpack-dev-server, there is no browser participation, so there is no source restriction. Add_header access-Control-allow-origin http://www.domain1.com; * add_header access-control-allow-credentials true; * add_header access-control-allow-credentials true; }}Copy the code








var xhr = new XMLHttpRequest(); // Whether the browser reads and writes cookies xhr.withCredentials = true; / / access proxy server in nginx XHR. Open (' get 'and' http://www.domain1.com:81/?user=admin ', true); xhr.send();Copy the code








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 cookie res.writeHead(200, {' set-cookie ': 'l=a123456; Path=/; Domain=www.domain2.com; HttpOnly' // HttpOnly: 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 proxies cross domains

Node middleware implements cross-domain proxy, which is roughly the same as nginx. It starts a proxy server to forward data. It can also modify the domain name in the cookie in the response header by setting the cookieDomainRewrite parameter to implement cookie writing in the current domain, facilitating interface login authentication.

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(); // Whether the browser reads and writes cookies xhr.withCredentials = true; / / access HTTP proxy - middleware proxy server XHR. Open (' get 'and' http://www.domain1.com:3000/login?user=admin ', true); xhr.send();Copy the code








var express = require('express'); var proxy = require('http-proxy-middleware'); var app = express(); App. Use ('/', the proxy ({/ / agent cross-domain target interface target: 'http://www.domain2.com:8080', changeOrigin: True, // Modify the response header to cross-domain and allow cookie onProxyRes: function(proxyRes, req, res) { res.header('Access-Control-Allow-Origin', 'http://www.domain1.com'); res.header('Access-Control-Allow-Credentials', 'true'); }, // rewrite: 'www.domain1.com' // can be false to indicate 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', / / agent cross-domain target interface changeOrigin: true, secure: false, / / when certain HTTPS proxy service error with cookieDomainRewrite: 'www.domain1.com' // Can be false to indicate that no modification is made}], noInfo: true}}Copy the code


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





The < div > user input: <input type="text"></div> <script src="./socket.io.js"></script> <script> var socket = io('http://www.domain2.com:8080'); On ('connect', function() {// Listen on the server message socket.on('message', function(msg) { console.log('data from server: ---> ' + msg); }); On ('disconnect', function() {console.log('Server socket has closed.'); }); }); document.getElementsByTagName('input')[0].onblur = function() { socket.send(this.value); }; </script>Copy the code











var http = require('http'); var socket = require('socket.io'); Var server = http.createserver (function(req, res) {res.writehead (200, {' content-type ': 'text/ HTML '}); 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... '); Socket.listen (server). On ('connection', function(client) { Function (MSG) {client.send('hello: '+ MSG); console.log('data from client: ---> ' + msg); }); On ('disconnect', function() {console.log(' client socket has closed.'); }); });Copy the code









The Denver nuggets