A cross-domain refers to a document or script under a domain that tries to request resources under another domain, where the cross-domain is generalized. This article is mainly to share with you the front-end cross-domain solution and hope to help everyone.
Generalized cross-domain:
1.) Resource jump: A link, redirect, form submission
2.) Resource embedding: <link>, <script>, , <frame> and other DOM tags, as well as the style of Background:url (), @font-face () and other documents outside the chain
3.) Script request: JS initiated Ajax request, Dom and JS object cross-domain operation, etc.
What we usually call cross-domain is narrow, is a kind of request scenario which is restricted by the browser homologous policy.
What is a homologous policy?
Same origin policy is a kind of agreement, introduced by Netscape Company 1995 Browser, it is the most core of the browser and the most basic security features, if the lack of the same-origin policy, the browser is vulnerable to XSS, CSFR and other attacks. The so-called homologous refers to the "protocol + domain + port" three of the same, even if two different domain names point to the same IP address, also non-homologous.
The same-origin policy restricts several behaviors:
1.) cookies, localstorage and indexdb cannot read 2.) DOM and JS objects cannot get 3.) AJAX requests cannot be sent
Common cross-domain scenarios
URL Description whether to allow traffic http://www.domain.com/a.jshttp://www.domain.com/b.js the same domain name, different files or paths allow HTTP// Www.domain.com/lab/c.jshttp://www.domain.com:8000/a.jshttp://www.domain.com/b.js the same domain name, different ports do not allow HTTP// Www.domain.com/a.jshttps://www.domain.com/b.js the same domain name, different protocols do not allow http://www.domain.com/a.jshttp:// 192.168.4.12/b.js domain name and domain name corresponding to the same IP does not allow the same http://www.domain.com/a.jshttp://x.domain.com/b.js primary domain, different subdomains do not allow http://domain.com/c.js http://www.domain1.com/a.jshttp://www.domain2.com/b.js different domain names are not allowed
Cross-Domain Solutions
1. Cross-domain through JSONP
2, Document.domain + iframe cross-domain
3, Location.hash + iframe
4, Window.name + iframe cross-domain
5, PostMessage cross-domain
6. Cross-domain resource sharing (CORS)
7, Nginx proxy cross-domain
8, Nodejs middleware agent cross-domain
9. WebSocket protocol Cross-domain
One, cross-domain through JSONP
Usually in order to alleviate the load of the Web server, we separate JS, css,img and other static resources to another independent domain name of the server, in the HTML page through the corresponding tag from the different domain load static resources, and by the browser allows, based on this principle, we can dynamically create script, Then request a URL with a parameter for cross-domain communication.
1.) Native Implementation:
<script> var script = document.createelement (' script '); Script.type = ' text/javascript '; The parameter is passed and the callback execution function is specified as onback script.src = ' http://www.domain2.com:8080/login?user=admin&callback=onBack '; Document.head.appendChild (script); Callback execution function Onback (res) { alert (json.stringify (res)); } </script>
The server returns as follows (the global function is executed on return):
Onback ({"Status": True, "user": "admin"})
2.) jquery Ajax:
$.ajax ({ URL: ' http://www.domain2.com:8080/login ', type: ' Get ', dataType: ' Jsonp ', //request by JSONP jsonpcallback: "Onback", //Custom callback function name data: {}});
3.) Vue.js:
this. The $http. Jsonp (' Http://www.domain2.com:8080/login ', { params: {}, Jsonp: ' Onback '}). Then (res) = { Console.log (res);})
Back-end node. JS code Example:
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 return set res.writehead ($, {' Content-type ': ' Text/javascript '}); Res.write (fn + ' (' + json.stringify (params) + ') '); Res.end ();}); Server.listen (' 8080 '); Console.log (' Server is running at port 8080 ... ');
Jsonp disadvantage: Only get one request can be implemented.
Second, Document.domain + iframe cross-domain
This scenario is limited to a cross-domain scenario where the primary domain is the same and the subdomain is different.
Realization principle: Two pages all through the JS force set Document.domain as the base master domain, realizes the same domain.
1.) 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>
2.) child window: (http://child.domain.com/b.html)
<script> document.domain = ' domain.com '; Gets the parent window variable alert (' Get JS data from parent---> ' + window.parent.user);</script>
Third, Location.hash + iframe cross-domain
Implementation principle: A To and b cross-domain mutual communication, through the intermediate page C to achieve. Three pages, different domains using the Location.hash of the IFRAME, the same domain between the direct JS access to communicate.
Specific implementation: A domain: a.html, b Domain: b.html A domain: C.html,a and b different domains can only pass the hash value one-way communication, B and C also different domains can only one-way communication, but C and a in the same domain, so C through Parent.parent access to a page all objects.
1.) a.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 '); Hash value to b.html setTimeout (function () { iframe.src = iframe.src + ' #user =admin '; }, +); callback method open to the same domain c.html function oncallback (res) { alert (' Data from c.html---> ' + res); } </script>
2.) b.html: (http://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 to the hash value from the a.html, and then pass it to c.html window.onhashchange = function () { iframe.src = iframe.src + Location.hash; }; </script>
3.) c.html: (http://www.domain1.com/c.html)
<script> //Listening to b.html the hash value Window.onhashchange = function () { //again by manipulating the same domain a.html JS callback, the results are passed back to Window.parent.parent.onCallback (' Hello: ' + location.hash.replace (' #user = ', ') '); }; </script>
Iv. Window.name + iframe cross-domain
The uniqueness of the Window.name property is that the name value persists after loading different pages (or even different domain names) and can support very long name values (2MB).
1.) a.html: (http://www.domain1.com/a.html)
var proxy = function (URL, callback) {var state = 0; var iframe = document.createelement (' iframe '); Load cross-domain page iframe.src = URL; The onload event is triggered 2 times, the 1th time the cross-domain page is loaded, and the data is retained in window.name iframe.onload = function () {if (state = = = 1) {//2nd time onl Oad (same domain proxy page) after the successful, read the same domain Window.name data callback (IFRAME.CONTENTWINDOW.NAME); Destoryframe (); } else if (state = = = 0) {//1th time the onload (cross-domain page) succeeds, switch to the same domain Proxy page iframe.contentWindow.location = ' http://www . domain1.com/proxy.html '; state = 1; } }; Document.body.appendChild (IFRAME); After acquiring the data, the IFRAME is destroyed and the memory is freed, which also guarantees the security (not being accessed by other domain 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);});
2.) proxy.html: (Http://www.domain1.com/proxy ....
Intermediate proxy page, same domain as a.html, content is empty.
3.) b.html: (http://www.domain2.com/b.html)
<script> window.name = ' This is domain2 data! '; </script>
Summary: Through the src attribute of the IFRAME to the local domain, the cross-domain data is transferred from the Window.name to the local domain by the IFRAME. This cleverly bypasses the browser's cross-domain access restrictions, but at the same time it is safe to operate.
V. 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, and it can be used to address issues such as the following:
A.) The data passing of the page and its open new window
B.) Message passing between multiple windows
C.) page and nested IFRAME message delivery
D.) Cross-domain data transfer for the above three scenarios
Usage: PostMessage (Data,origin) method accepts two parameters
The DATA:HTML5 specification supports any basic type or replicable object, but some browsers only support strings, so it is best to serialize with json.stringify () when you pass the parameter.
Origin: Protocol + host + port number, can also be set to "*", indicating can be passed to any window, if you want to specify the same as the current window is set to "/".
1.) a.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 ' }; Transmitting cross-domain data iframe.contentWindow.postMessage (json.stringify (data), ' http://www.domain2.com ') to domain2; }; Accept domain2 Return Data window.addeventlistener (' message ', function (e) { alert (' Data from domain2---> ' + e.data) ; }, False);</script>
2.) b.html: (http://www.domain2.com/b.html)
<script> //Receive domain1 Data window.addeventlistener (' message ', function (e) { alert (' data from Domain1---> ' + e.data); var data = Json.parse (e.data); if (data) { Data.number = +; After processing, send back domain1 window.parent.postMessage (json.stringify (data), ' http://www.domain1.com '); } , False);</script>
Vi. cross-domain resource sharing (CORS)
Common cross-domain request: Only the server set Access-control-allow-origin, the front-end does not need to set up, to bring a cookie request: both front and rear needs to be set.
Note that the cookie read is a cookie for the domain of the cross-domain request interface, not the current page, due to the restriction of the same Origin policy. If you want to implement the current page cookie write, you can refer to the following: seven, Nginx reverse proxy set Proxy_cookie_domain and eight, Nodejs middleware agent cookiedomainrewrite parameter settings.
Currently, all browsers support this feature (IE8+:IE8/9 needs to use Xdomainrequest objects to support Cors), and Cors has become the mainstream cross-domain solution.
1. Front-end settings:
1.) Native Ajax
Whether the front-end settings are with cookiexhr.withcredentials = true;
Example code:
var xhr = new XMLHttpRequest (); IE8/9 needs window. Xdomainrequest compatible//front-end settings with cookiexhr.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 = =) { alert (xhr.responset EXT); }};
2.) JQuery Ajax
$.ajax ({ ... Xhrfields: { withcredentials:true ///front-end settings with Cookie }, crossdomain:true, //will have the request header contain additional cross-domain information, But will not contain cookies ... });
3.) Vue Framework
Add the following code to the Ajax component in the Vue-resource package:
Vue.http.options.credentials = True
2. Service-Side settings:
If the backend settings are successful, the front-end browser console will not have cross-domain error messages, and conversely, the description is not successful.
1.) Java background:
/* * Importing package: Import Javax.servlet.http.HttpServletResponse; * Interface parameters defined: HttpServletResponse response */response.setheader ("Access-control-allow-origin", "http://www.domain1.com "); If the port needs to write full (protocol + domain + port) response.setheader ("Access-control-allow-credentials", "true");
2.) Nodejs Background Example:
var http = require (' http '), var server = Http.createserver (), var qs = require (' querystring '), Server.on (' request '), Function (req, res) { var postdata = '; Data block receive in req.addlistener (' Data ', function (chunk) { postdata + = chunk; }); Data received Req.addlistener (' End ', function () { postdata = Qs.parse (postdata); Cross-domain background settings res.writehead ($, { ' access-control-allow-credentials ': ' true ', //back-end allow cookies to be sent Access-control-allow-origin ': ' http://www.domain1.com ', //Allow access to the domain (protocol + domain + port) ' Set-cookie ': ' l=a123456; path=/;D omain=www.domain2.com; HttpOnly ' //HttpOnly: The script cannot read the cookie }); Res.write (Json.stringify (postdata)); Res.end (); }); Server.listen (' 8080 '); Console.log (' Server is running at port 8080 ... ');
Seven, Nginx proxy cross-domain
1, Nginx Configuration resolution Iconfont cross-domain
Browser cross-domain access JS, CSS, IMG and other regular static resources are licensed by the same-origin policy, but the Iconfont font file (eot|otf|ttf|woff|svg) exception, at this time, you can add the following configuration in Nginx static resource server.
Location/{ add_header access-control-allow-origin *;}
2, Nginx reverse proxy interface cross-domain
Cross-domain principle: the same origin policy is the browser's security policy, not part of the HTTP protocol. The server-side invoke HTTP interface simply uses the HTTP protocol, does not execute the JS script, does not require the same-origin policy, and there is no spanning problem.
Implementation of ideas: through Nginx configuration of a proxy server (domain name and domain1 the same, the port is different) to do a springboard, reverse proxy access to the Domain2 interface, and can also modify the cookie domain information, convenient current domain cookie write, to achieve cross-domain login.
Nginx Specific configuration:
#proxy服务器server { listen Bayi; server_name www.domain1.com; Location/{ proxy_pass http://www.domain2.com:8080; #反向代理 proxy_cookie_domain www.domain2.com www.domain1.com; #修改cookie里域名 index index.html index.htm; # when accessing Nignx with Webpack-dev-server and other middleware proxy interfaces, there is no browser participation at this time, so there is no homologous limitation, the following cross-domain configuration is not enabled Add_header access-control-allow-origin http://www.domain1.com; #当前端只跨域不带cookie时, can be * add_header access-control-allow-credentials true; }}
1.) Front-End code example:
var xhr = new XMLHttpRequest ();//Front-end switch: whether the browser reads and writes cookiexhr.withcredentials = true;//access to the proxy server in Nginx xhr.open (' Get ', ' http:/ /www.domain1.com:81/?user=admin ', true); Xhr.send ();
2.) Nodejs Background Example:
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 the Cookie res.writehead (" set-cookie ': ' l=a123456") to the forward platform; path=/;D omain=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 ... ');
Viii. Nodejs Middleware Agent cross-domain
Node middleware implementation of cross-domain proxy, the principle is the same as Nginx, all by starting a proxy server to achieve data forwarding, you can also set the Cookiedomainrewrite parameter to modify the domain name in the cookie in the response header, to achieve the current domain cookie write, Convenient interface login authentication.
1, non-VUE framework cross-domain (2 cross-domain)
Use node + Express + Http-proxy-middleware to build a proxy server.
1.) Front-End code example:
var xhr = new XMLHttpRequest ();//Front-end switch: whether the browser reads and writes cookiexhr.withcredentials = true;//Access Http-proxy-middleware Proxy Server Xhr.open (' Get ', ' http://www.domain1.com:3000/login?user=admin ', true); Xhr.send ();
2.) Middleware server:
var express = require (' Express '), var proxy = require (' Http-proxy-middleware '), var app = Express (), App.use ('/', proxy ({ c0/>//Proxy cross-domain destination interface target : ' http://www.domain2.com:8080 ', changeorigin:true, //Modify response header information, implement 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 '); }, //Modify the cookie domain name in the response message cookiedomainrewrite: ' Www.domain1.com ' //can be false, indicating no modification}); app.listen; Console.log (' Proxy server is listen at Port 3000 ... ');
3.) Nodejs Backstage with (vi: NGINX)
2. Cross-domain (1 cross-domain) of the Vue framework
Cross-domain using node + webpack + Webpack-dev-server Proxy interface. In the development environment, since the Vue rendering service and the interface Proxy service are all webpack-dev-server the same, there is no longer a cross-domain between the page and the proxy interface, and there is no need to set headers cross-domain information.
Webpack.config.js Partial 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 proxy for some HTTPS service error Cookiedomainrewrite: ' www.domain1.com ' //can be false, indicating not modified }], noinfo:true }}
Ix. websocket Protocol cross-domain
WebSocket protocol is a new protocol for HTML5. It implements full-duplex communication between the browser and the server while allowing cross-domain communication, which is a good implementation of server push technology.
Native WebSocket API is not easy to use, we use Socket.io, which encapsulates the WebSocket interface nicely, provides a simpler, more flexible interface, and is backwards compatible with browsers that do not support websocket.
1.) Front-end code:
<p>user input:<input type= "text" ></p><script src= "./socket.io.js" ></script>< Script>var socket = io (' http://www.domain2.com:8080 ');//Connection successfully processed Socket.on (' Connect ', function () { //listener service-side message socket.on (' message ', function (msg) { console.log (' Data from server:---> ' + msg); }); The listener server closes socket.on (' Disconnect ', function () { console.log (' Server socket has closed. ');}); document.getElementsByTagName (' input ') [0].onblur = function () { socket.send (this.value);}; </script>
2.) Nodejs Socket background:
var http = require (' http '); var socket = require (' Socket.io ');//Start HTTP service var Server = Http.createserver (function (req, res) {Res.writehead ($, {' Content-type ': ' text/html '}); Res.end ();}); Server.listen (' 8080 '); Console.log (' Server is running at port 8080 ... '); /Monitor Socket Connection 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. '); });});