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, redirection, form submission

2.) Resource embedding: <link>, <script>, <img>, <frame> and other DOM tags, as well as background: URL (), @font-face() and other file external links in styles

3.) Script request: AJAX request initiated by JS, cross-domain operation of DOM and JS objects, etc


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 read

2.) DOM and Js objects are not available

3.) AJAX requests cannot be sent


Common cross-domain scenarios



URL indicates whether communication is allowed

http://www.domain.com/a.js

The same domain name, http://www.domain.com/b.js allows different file or path

http://www.domain.com/lab/c.js

 

http://www.domain.com:8000/a.js

The same domain name http://www.domain.com/b.js, different port Don't allow

http://www.domain.com/a.js

The same domain name https://www.domain.com/b.js, different protocols Don't allow

http://www.domain.com/a.js

http://192.168.4.12/b.js A domain name 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

Different domain name http://www.domain2.com/b.js Don't allow


Cross-domain solutions


1. Cross domains through JSONP

Document.domain + iframe cross domain

3. Location. hash + iframe

4, window.name + iframe cross domain

5. PostMessage crosses domains

6. Cross-domain Resource Sharing (CORS)

7, Nginx proxy cross domain

Nodejs middleware proxy across domains

9. WebSocket protocol is cross-domain


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>


The server returns the following (executes the global function when it returns) :



onBack({"status": true, "user": "admin"})


2. Jquery Ajax:


$.ajax({

    url: 'http://www.domain2.com:8080/login',

    type: 'get',

DataType: 'jSONp ', // request type is JSONp

JsonpCallback: "onBack", // custom callback function name

    data: {}

});


3.) the vue. Js:


this.$http.jsonp('http://www.domain2.com:8080/login', {

    params: {},

    jsonp: 'onBack'

}).then((res) => {

    console.log(res);

})


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... ');


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.) 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>


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


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.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');

 

// 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>


2.) b.h 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 for hash values from A.html and pass them to C.HTML

    window.onhashchange = function () {

        iframe.src = iframe.src + location.hash;

    };

</script>


3.) c. HTML: (http://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>


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.h HTML: (http://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);

});


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>


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.) page and the new window it opens

B.) Message passing between multiple Windows

C.) page with nested iframe message passing

D.) cross-domain data transfer in the above three scenarios


Usage: The postMessage(data, Origin) method takes two arguments

Data: The HTML5 specification supports any primitive type or copiable 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 “*”, indicating that the message can be sent to any window. If you want to specify the origin of the message and the current window, set this parameter 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'

        };

// 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>


2.) b.h HTML: (http://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>


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;


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);

    }

};


2.) the jQuery ajax


$.ajax({

.

   xhrFields: {

WithCredentials: true // The front end sets whether to contain cookies

   },

CrossDomain: true, // causes the header to contain additional cross-domain information, but not cookies

.

});


3.) VUE framework


Add the following code to the Vue-Resource wrapped Ajax component:


Vue.http.options.credentials = true


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 is defined in the interface parameters

* /

response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com"); // Write full (protocol + domain + port)

response.setHeader("Access-Control-Allow-Credentials", "true");


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 + 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... ');


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 *;

}


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;

    }

}


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();


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... ');


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();


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' // Can be false to indicate no modification

}));

 

app.listen(3000);

console.log('Proxy server is listen at port 3000... ');


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,

CookieDomainRewrite: 'www.domain1.com' // Can be false to indicate no modification

}].

        noInfo: true

    }

}


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>


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) {

Send ('hello: '+ MSG);

        console.log('data from client: ---> ' + msg);

    });

 

// Disconnect processing

    client.on('disconnect', function() {

        console.log('Client socket has closed.');

    });

});


Via quiet precipitation