Front-end cross-domain solution sharing

Source: Internet
Author: User
Tags nginx reverse proxy
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. '); });});

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.