What is cross-domain?
Cross-domain refers to a document or script under one domain trying to request resources under another domain. Here cross-domain is broad.
Broadly cross-domain:
-
1.) Resource jump: A link, redirection, form submission
-
2.) Resource Embedding:<link>、<script>
In fact, what we usually call cross-domain is a narrow sense, and is a type of request scenario restricted by the browser's homologous policy.
What is a homologous strategy?
Same origin policy/SOP (Same origin policy) is a convention introduced by Netscape in 1995. It is the most core and basic security function of the browser. If the same origin policy is missing, the browser is vulnerable to attacks such as XSS and CSFR. The so-called homologous origin refers to the same "protocol + domain name + port". Even if two different domain names point to the same IP address, they are not homologous.
Homologous policies restrict the following behaviors:
-
1.) Cookies, LocalStorage, and IndexDB cannot be read
-
2.) DOM and Js objects cannot be obtained
-
3.) AJAX request cannot be sent
Common cross-domain scenarios
-
URLDescription Whether communication is allowed
-
http:///
-
http:/// Same domain name, different files or paths Allow /lab/ :8000/ / Same domain name, different ports Not allowed // Same domain name, different protocols Not allowed / http://192.168.4.12/ The domain name and domain name correspond to the same ip Not allowed // The main domain is the same and the subdomain is different Not allowed / http:/// http:/// http:/// different domain names Not allowed
Cross-domain solutions
1、passjsonpCross-domain
2、 + iframeCross-domain
3、 + iframe
4、 +iframeCross-domain
5、 postMessageCross-domain
6、Cross-domain resource sharing (CORS)
7、 nginxAgent cross-domain
8、 nodejsMiddleware Agent Cross-domain
9、 WebSocketProtocol cross-domain
10. Image Ping
1. Cross-domain through jsonp
JSONP (JSON with padding) consists of two parts: callbackfunctionand data. A callback function is a function that should be called on the page when the response arrives. The name of the callback function is generally formulated in the request. And the data is the JSON data passed into the callback function. Usually in order to reduce the load of the web server, we separate static resources such as js, css, img and other static resources to another server with independent domain names, and then load static resources from different domain names through corresponding tags in the html page, which is allowed by the browser. Based on this principle, we can create script dynamically and then request a URL with a parameter 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 = 'http://:8080/login?user=admin&callback=onBack'; (script); // Callback execution function function onBack(res) { alert((res)); }</script>
The server returns the following (the global function is executed when it returns):
onBack({"status": true, "user": "admin"})
2.)jquery ajax:
-
$.ajax({
-
url: 'http://:8080/login',
-
type: 'get',
-
dataType: 'jsonp', // The request method is jsonp jsonpCallback: "onBack", // Custom callback function name data: {} });
3.)vue.js:
-
this.$http.jsonp('http://:8080/login', {
-
params: {},
-
jsonp: 'onBack' }).then((res) => { console.log(res); })
rear endCode 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 returns settings (200, { 'Content-Type': 'text/javascript' }); (fn + '(' + (params) + ')'); (); }); ('8080'); ('Server is running at port 8080...');
Disadvantages of jsonp: 1. Only get one request can be implemented. 2. JSONP is to load code execution from other domains. If other domains are not safe, it is likely to contain some malicious code in the response, and at this time there is no way to investigate except to completely abandon the JSONP call. Therefore, when using a web service that is not operated and maintained by yourself, you must ensure that it is safe and reliable. 3. It is not easy to determine whether the JSONP request failed. Although HTML5 has added an onerror event handler to the <script> element, it has not yet received any browser support. To this end, developers have to use a timer to detect whether a response has been received within a specified time, but even this cannot be satisfactory. After all, it is not the speed of every user to surf the Internet.
2. + iframe cross-domain
This solution is only for cross-domain application scenarios where the main domain is the same and the subdomain is different.
Implementation principle: Both pages are forced to be set as the basic main domain through js, and the same domain is implemented.
1.) Parent window: (/)
<iframe id="iframe" src="/"></iframe> <script> document.domain = ''; var user = 'admin'; </script>
2.) Sub-window: (/)
<script> document.domain = ''; // Get the variable alert('get js data from parent ---> ' + );</script>
3. + iframe cross-domain
Implementation principle: a and b want to communicate across domains and implement it through intermediate page c. Three pages, different domains use the Iframe's value to communicate directly between the same domains.
Specific implementation: Domain A: -> Domain B: -> Domain A: Different domains a and b can only communicate in one-way through hash values, and different domains b and c can only communicate in one-way, but c and a are the same domain, so c can access all objects on page a by access.
1.):(/)
<iframe id="iframe" src="http:///" style="display:none;"></iframe> <script> var iframe = document.getElementById('iframe'); // Pass hash value to setTimeout(function() { = + '#user=admin'; }, 1000); // Open callback method to the same domain function onCallback(res) { alert('data from ---> ' + res); }</script>
2.):(/)
<iframe id="iframe" src="http:///" style="display:none;"></iframe> <script> var iframe = document.getElementById('iframe'); // Listen to the hash value passed and pass it to = function () { = + ; };</script>
3.):(/)
<script> // Listen to the hash value = function () { // Then pass the result back by operating the js callback in the same domain ('hello: ' + ('#user=', '')); };</script>
4. + iframe cross-domain
The uniqueness of the attribute: the name value still exists after loading on different pages (even different domain names), and can support very long name values (2MB).
1.):(/)
var proxy = function(url, callback) { var state = 0; var iframe = document.createElement('iframe'); // Load cross-domain page = url; // The onload event will fire twice, the first time the cross-domain page is loaded, and the data is retained in = function() { if (state === 1) { // After the second time onload (same domain proxy page) is successful, read the data in the same domain callback(); destoryFrame(); } else if (state === 0) { // After the first time onload (same domain page) is successful, switch to the same domain proxy page = 'http:///'; state = 1; } }; (iframe); // After obtaining the data, destroy this iframe and free up memory; this also ensures security (not accessed by other domain frame js) function destoryFrame() { (''); (); (iframe); } }; // Request cross-domain b page data proxy('http:///', function(data){ alert(data); });
2.):(/proxy....
The intermediate proxy page, as in the same domain, only if the content is empty.
3.):(/)
<script> window.name = 'This is domain2 data!'; </script>
Summary: Through the src attribute of the iframe, the cross-domain data is transferred from the external domain to the local domain from the external domain to the local domain. This cleverly bypasses the browser's cross-domain access restrictions, but at the same time it is a safe operation.
5. 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 delivery of the page and its open new window
b.) Message delivery between multiple windows
c.) Page with nested iframe messaging
d.) Cross-domain data transmission in the above three scenarios
Usage: the postMessage(data,origin) method accepts two parameters
data: The html5 specification supports any basic type or replicable objects, but some browsers only support strings, so it is best to use () to serialize when passing parameters.
origin: Protocol + host + port number, can also be set to "*", indicating that it can be passed to any window, and set to "/" if you want to specify the same origin as the current window.
1.):(/)
<iframe id="iframe" src="http:///" style="display:none;"></iframe> <script> var iframe = document.getElementById('iframe'); iframe.onload = function() { var data = { name: 'aym' }; // Transfer cross-domain data to domain2 ((data), 'http://'); }; // Accept domain2 return data ('message', function(e) { alert('data from domain2 ---> ' + ); }, false);</script>
2.):(/)
<script> // Receive domain1's data ('message', function(e) { alert('data from domain1 ---> ' + ); var data = (); if (data) { = 16; // Send back domain1 ((data), 'http://'); } }, false);</script>
6. Cross-domain resource sharing (CORS)
Normal cross-domain request: Only the server can set Access-Control-Allow-Origin, but the front-end does not need to be set.
Request with cookie: Both front and back ends need to set fields. Also, note that the cookie brought is the cookie of the domain where the cross-domain request interface is located, not the current page.
Currently, all browsers support this feature (IE8+: IE8/9 requires the use of XDomainRequest object to support CORS), and CORS has also become a mainstream cross-domain solution.
1. Front-end settings:
1.) Native ajax
-
// Whether the front-end settings include cookies
-
xhr.withCredentials = true;
Sample code:
-
var xhr = new XMLHttpRequest(); // IE8/9 requires compatibility
-
-
// Whether the front-end settings include cookies
-
xhr.withCredentials = true; xhr.open('post', 'http://: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.)jQuery ajax
-
$.ajax({
-
...
-
xhrFields: {
-
withCredentials: true // Whether the front-end settings include cookies
-
},
-
crossDomain: true, // Will make the request header contain extra information across domains, but will not contain cookies... });
3.) Vue framework encapsulated ajax in vue-resourceComponentsAdd the following code to:
Vue.http.options.credentials = true
2. Server settings:
If the backend is set successfully, the front-end browser console will not have cross-domain error messages. Otherwise, it means that the setting is not successful.
1.) Java backend:
-
/*
-
* Import package: import;
-
* Defined in interface parameters: HttpServletResponse response
-
*/
-
("Access-Control-Allow-Origin", "http://"); // If there is a port, please write all (protocol + domain name + port)
-
("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 reception ('data', function(chunk) { postData += chunk; }); // Data reception is completed ('end', function() { postData = (postData); // Cross-domain background settings (200, { 'Access-Control-Allow-Credentials': 'true', // Backend allows sending cookies 'Access-Control-Allow-Origin': 'http://', // Allow access domain (protocol + domain name + port) 'Set-Cookie': 'l=a123456;Path=/;Domain=;HttpOnly' // HttpOnly: The script cannot read cookies }); ((postData)); (); }); }); ('8080'); ('Server is running at port 8080...');
seven,nginxAgent cross-domain
1. nginx configuration solves iconfont cross-domain
The browser's cross-domain access to 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) is exception. At this time, the following configuration can be added to the static resource server of nginx.
-
location / {
-
add_header Access-Control-Allow-Origin *;
-
}
2. nginx reverse proxy interface cross-domain
Cross-domain principle: Same-origin policy is a browser's security policy, not part of the HTTP protocol. The server-side calls the HTTP interface only using the HTTP protocol, does not execute JS scripts, does not require a same-origin policy, and there is no crossover problem.
Implementation idea: Configure a proxy server through nginx (domain name is the same as domain 1 and has different ports) as a springboard machine, reverse proxy accesses the domain2 interface, and can modify the domain information in the cookie by the way, so as to facilitate the writing of the current domain cookie and realize cross-domain login.
nginx specific configuration:
-
#proxy server
-
server {
-
listen 81;
-
server_name 1.com; location / { proxy_pass http://2.com:8080; #Reverse proxy_cookie_domain2.com 1.com; #Modify the domain name in the cookieindex index.html index.htm; # When accessing nignx using middleware proxy interfaces such as webpack-dev-server, there is no browser participation at this time, so there is no homologous restriction. The following cross-domain configurations cannot be enabledadd_header Access-Control-Allow-Origin http://1.com; # When the current end only cross-domain without cookies, it can be* add_header Access-Control-Allow-Credentials true; } }
1.) Front-end code example:
-
var xhr = new XMLHttpRequest();
-
-
// Front-end switch: Does the browser read and write cookies
-
xhr.withCredentials = true;
-
-
// Access the proxy server in nginx ('get', 'http://:81/?user=admin', true); ();
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 cookies to the front desk (200, { 'Set-Cookie': 'l=a123456;Path=/;Domain=;HttpOnly' // HttpOnly: The script cannot be read }); ((params)); (); }); ('8080'); ('Server is running at port 8080...');
8. Nodejs middleware agent cross-domain
nodeMiddleware implements cross-domain proxy, and the principle is roughly the same as nginx. Both of them realize data forwarding by enabling a proxy server.
1. Cross-domain (2 times cross-domain) of non-vue frameworks
Use node + expression + http-proxy-middleware to build a proxy server.
1.) Front-end code example:
-
var xhr = new XMLHttpRequest();
-
-
// Front-end switch: Does the browser read and write cookies
-
xhr.withCredentials = true;
-
-
// Access the http-proxy-middleware proxy server ('get', 'http://:3000/login?user=admin', true); ();
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://:8080', changeOrigin: true, // Modify response header information to implement cross-domain and allow cookies onProxyRes: function(proxyRes, req, res) { ('Access-Control-Allow-Origin', 'http://'); ('Access-Control-Allow-Credentials', 'true'); }, // Modify the cookie domain name in the response information cookieDomainRewrite: '' // It can be false, indicating that it does not modify })); (3000); ('Proxy server is listened at port 3000...');
3.) Nodejs background same as (six: nginx)
2. Cross-domain (1 cross-domain) of the vue framework
Utilize node + webpack + webpack-dev-serverProxy interfaces cross domain. In the development environment, since the vue rendering service and interface proxy service are the same as webpack-dev-server, the page and the proxy interface are no longer cross-domain, and there is no need to set headers cross-domain information.
Some configurations:
-
module.exports = {
-
entry: {},
-
module: {},
-
...
-
devServer: {
-
historyApiFallback: true, proxy: [{ context: '/login', target: 'http://:8080', // Agent cross-domain target interface changeOrigin: true, cookieDomainRewrite: '' // It can be false, indicating that it does not modify }], noInfo: true } }
9. WebSocket protocol cross-domain
WebSocket protocol is a new protocol for HTML5. It realizes full duplex communication between the browser and the server, and allows cross-domain communication, which is a good implementation of server push technology. The native WebSocket API is not very convenient to use. When we use it, it encapsulates the webSocket interface well, provides a simpler and more 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="./"></script> <script> var socket = io('http://:8080'); // Connection successfully handled ('connect', function() { // Listen to server messages ('message', function(msg) { ('data from server: ---> ' + msg); }); // Listen to server shutdown ('disconnect', function() { ('Server socket has closed.'); }); }); ('input')[0].onblur = function() { (); };</script>
2.) Nodejs socket background:
-
var http = require('http');
-
var socket = require(''); // Enable http service var server = (function(req, res) { (200, { 'Content-type': 'text/html' }); (); }); ('8080'); ('Server is running at port 8080...'); // Listen to socket connections (server).on('connection', function(client) { // Receive information ('message', function(msg) { ('hello:' + msg); ('data from client: ---> ' + msg); }); // Disconnect processing ('disconnect', function() { ('Client socket has closed.'); }); });