Common front-end cross domain solutions

Time:2022-2-3

What is cross domain?

Cross domain refers to a document or script in one domain trying to request resources in another domain. Here, cross domain is generalized.

Broad cross domain:

  • 1. Resource jump: a link, redirection, form submission
  • 2. Resource embedding:<link>、<script>、<img>、<frame>And other DOM tags, as well as the external chain of files such as background: url(), @ font face()
  • 3. Script request: Ajax request initiated by JS, cross domain operation of DOM and JS objects, etc

In fact, what we usually call cross domain is in a narrow sense, which is defined by the browserHomologous strategyA restricted type of request scenario.

What is homology strategy?

The same origin policy (SOP) is an agreement. The browser was 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 vulnerableXSSCSFRAnd so on.

The so-called homology means that “protocol + domain name + port” are the same. Even if two different domain names point to the same IP address, they are not homologous.

The same origin policy limits 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

Cross domain solutions

  • 1. Cross domain through jsonp
  • 2. Cross domain resource sharing (CORS)
  • 3. Nginx proxy cross domain
  • 4. Nodejs middleware agent cross domain
  • 5. Websocket protocol cross domain
  • 6. PostMessage cross domain
  • 7、 document. Domain + iframe cross domain
  • 8、 location.hash + iframe
  • 9、 window.name+Iframe cross domain

1、 Cross domain through jsonp

Jsonp is the abbreviation of JSON with padding. It is an unofficial protocol, which allows the integration of script tags on the server side to return to the client, and realizes cross domain access in the form of JavaScript callback (this is only a simple implementation form of jsonp).

Generally, in order to reduce the load of the web server, we separate the static resources such as JS, CSS and img to another server with independent domain name, and then load the static resources from different domain names through the corresponding tags in the HTML page, which is allowed by the browser. Based on this principle, we can dynamically create scripts and then request a web address with parameters to realize cross domain communication.

1.1. Generation of jsonp

The generation of jsonp includes the following aspects:

  • 1. Ajax directly requests ordinary files, which has the problem of cross domain unauthorized access, whether it is a static page.
  • 2. When calling JS files, it is not affected by cross domain, such as introducing jQuery framework or calling pictures. Calling CSS files is also not affected by cross domain!
  • 3. All tags with SRC attribute can cross domains, such as<script><img><iframe>
  • 4. If you want to access data across domains through pure web, there is only one possibility, that is to load the data on the remote server into JS format files.
  • 5. JSON is also a lightweight data format, which is also natively supported by JS.
  • 6. In order to facilitate the client to use data, an informal transmission protocol has gradually formed, which is called jsonp. One of the key points of this protocol is to allow the user to pass a callback parameter to the server.

1.2 implementation principle of jsonp

<script>The SRC attribute of the tag is not constrained by the same origin policy, so the script on any server can be obtained and executed.

We can create a callback function, call this function on the server side, and pass in the data as a parameter to complete the callback. Finally, the data can be obtained by filling JSON data into the callback function.

Disadvantages of jsonp: it can only implement one request of get.

1.3. Implementation of jsonp

1.3.1. Native implementation

 <script type='text/javascript'>
    window.jsonpCallback = function (res) {
        console.log(res)
    }
</script>
<script src='https://localhost:8080/api/jsonp?cb=jsonpCallback' type='text/javascript'></script>

Server processing:

const Koa = require('koa');
const app = new Koa();

app.use(async (ctx, next) => {
  if (ctx.path === '/api/jsonp') {
    const { cb } = ctx.query;
    const data = "www.shanzhonglei.com";
    ctx.body = `${cb}(data)`;
    return;
  }
})
app.listen(8080);

Resolution:

  • 1. When the second script is executed, the request will be initiated.
  • 2. Back end getcb, we know that there will be a function called jsonpcallback at the front end to receive the data that the back end wants to return, and at the back end, you only need to write jsonpcallback () in the return body.
  • 3. The front end gets the content jsonpcallback returned by the back end(“www.shanzhonglei.com“), it is found that there is a statement executing a function, so we will execute the jsonpcallback method in the first script, and the passed parameters are the data we want to obtain.

1.3.2、jquery ajax

$.ajax({
    url: 'http://localhost:8080/login',
    type: 'get',
    Datatype: 'jsonp', // the request method is jsonp
    Jsonpcallback: "handlecallback", // custom callback function name
    data: {}
});

1.3.3、vue

this.$http.jsonp('http://localhost:8080/login', {
    params: {},
    jsonp: 'handleCallback'
}).then((res) => {
    console.log(res); 
})

2、 Document Domain + iframe cross domain

This scheme is limited to cross domain application scenarios with the same primary domain and different sub domains.

Implementation principle

Both pages use js to force the setting of document Domain as the basic primary domain, the same domain is realized.

2.1. Parent window

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

<iframe src="https://child.domain.com/b.html"></iframe>
<script>
    document.domain = 'domain.com';
    var user = 'admin';
</script>

2.2. Sub window

http://child.domain.com/b.html

<script>
    document.domain = 'domain.com';
    //Gets the variable in the parent window
    alert('get js data from parent ---> ' + window.parent.user);
</script>

3、 Location Hash + iframe cross domain

Implementation principle

A wants to communicate with B across domains through the middle page C. Three pages, using iframe location between different domains Hash value transfer, direct JS access between the same fields to communicate.

Concrete implementation

Domain a: a.html – > domain B: b.html – > domain a: c.html. Different domains of a and B can only communicate one way through hash value, and different domains of B and C can only communicate one way, but C and a are in the same domain, so C can communicate through parent Parent accesses all objects on the a page.

a.html

http://www.domain1.com/a.html

<iframe src="https://www.domain2.com/b.html" style="display:none;"></iframe>
<script>
    var iframe = document.getElementById('iframe');

    //Pass hash value to b.html
    setTimeout(function() {
        iframe.src = iframe.src + '#user=admin';
    }, 1000);

    //Callback method open to c.html in the same domain
    function onCallback(res) {
        alert('data from c.html ---> ' + res);
    }
</script>

b.html

http://www.domain2.com/b.html

<iframe src="https://www.domain1.com/c.html" style="display:none;"></iframe>
<script>
    var iframe = document.getElementById('iframe');

    //Listen for the hash value from a.html and then pass it to c.html
    window.onhashchange = function () {
        iframe.src = iframe.src + location.hash;
    };
</script>

c.html

http://www.domain1.com/c.html

<script>
    //Listen for the hash value from b.html
    window.onhashchange = function () {
        //Then, the result is returned by operating the JS callback of a.html in the same domain
        window.parent.parent.onCallback('hello: ' + location.hash.replace('#user=', ''));
    };
</script>

IVwindow.name+Iframe cross domain

window. The uniqueness of the name attribute: the name value still exists after different pages (even different domain names) are loaded, and can support very long name value (2MB).

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 will be triggered twice. The cross domain page will be loaded for the first time and the data will be saved in the window name
    iframe.onload = function() {
        if (state === 1) {
            //After the second onload (same domain proxy page) succeeds, read the same domain window Data in name
            callback(iframe.contentWindow.name);
            destoryFrame();

        } else if (state === 0) {
            //After the first onload (cross domain page) is successful, switch to the same domain proxy page
            iframe.contentWindow.location = 'http://www.domain1.com/proxy.html';
            state = 1;
        }
    };

    document.body.appendChild(iframe);

    //After obtaining the data, destroy the iframe to free the memory; This also ensures security (not accessed by frame JS in other domains)
    function destoryFrame() {
        iframe.contentWindow.document.write('');
        iframe.contentWindow.close();
        document.body.removeChild(iframe);
    }
};

proxy.html

http://www.domain1.com/proxy....
The intermediate agent page has the same domain as a.html, and the content can be empty.

b.html

http://www.domain2.com/b.html

<script>
    window.name = 'This is domain2 data!';
</script>

Through the SRC attribute of iframe, the external domain is transferred to the local domain, and the cross domain data is transferred from the window of iframe Name is passed from the foreign domain to the local region. This skilfully 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 one of the few window attributes that can operate across domains. It can be used to solve the following problems:

  • 1. Data transfer between the page and the new window it opens
  • 2. Message passing between multiple windows
  • 3. Page and nested iframe messaging
  • 4. Cross domain data transfer in the above three scenarios

usage

The PostMessage (data, origin) method accepts two parameters

data: the HTML5 specification supports any basic type or replicable object, but some browsers only support strings, so it’s best to use JSON when passing parameters Stringify() serialization.

origin: Protocol + host + port number, which can also be set to “*”, indicating that it can be passed to any window. If you want to specify the same source as the current window, set it to “/.

a.html

http://www.domain1.com/a.html

<iframe src="https://www.domain2.com/b.html" style="display:none;"></iframe>
<script>       
    var iframe = document.getElementById('iframe');
    iframe.onload = function() {
        var data = {
            name: 'aym'
        };
        //Transfer cross domain data to domain2
        iframe.contentWindow.postMessage(JSON.stringify(data), 'http://www.domain2.com');
    };

    //Accept the data returned by domain2
    window.addEventListener('message', function(e) {
        alert('data from domain2 ---> ' + e.data);
    }, false);
</script>

b.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 after processing
            window.parent.postMessage(JSON.stringify(data), 'http://www.domain1.com');
        }
    }, false);
</script>

6、 Cross domain resource sharing (CORS)

Common cross domain request: only the server can set access control allow origin. The front end does not need to be set. If you want to bring a cookie request. Both front and rear ends need to be set.

It should be noted that due to the restriction of the homology policy, the cookie read is the cookie of the domain where the cross domain request interface is located, not the current page.

At present, all browsers support this function (IE8 +: IE8 / 9 needs to use xdomainrequest object to support CORS), and CORS has also become a mainstream cross domain solution.

Front end settings

1. Native Ajax

//Front end setting whether to bring cookies
xhr.withCredentials = true;

Example code:

var xhr = new XMLHttpRequest(); //  IE8 / 9 needs window Xdomainrequest compatible

//Front end setting whether to bring cookies
xhr.withCredentials = true;

xhr.open('post', 'http://localhost: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 // front end setting whether to bring cookies
   },
   Crossdomain: true, // the request header will contain additional information across domains, but will not contain cookies
    ...
});

3、vue

//Axios settings:
axios.defaults.withCredentials = true

Vue resource settings:
Vue.http.options.credentials = true

Server settings

If the back-end settings are successful, the front-end browser console will not display cross domain error messages. On the contrary, it indicates that the settings are not successful.

1. Java background

/*
 *Import package: import javax servlet. http. HttpServletResponse;
 *Interface parameters: httpservletresponse
 */

//Domain name that allows cross domain access: if there is a port, write it all (protocol + domain name + port). If there is no port, don't add '/' at the end
response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com"); 

//Allow authentication cookies on the front end: after this option is enabled, the domain name above cannot be '*', you must specify a specific domain name, otherwise the browser will prompt
response.setHeader("Access-Control-Allow-Credentials", "true"); 

//Two common custom headers that need to be set at the back end when prompting options pre check
response.setHeader("Access-Control-Allow-Headers", "Content-Type,X-Requested-With");

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 receiving
    req.addListener('data', function(chunk) {
        postData += chunk;
    });

    //Data reception completed
    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 name + port)
            /* 
             *The cookie set here is domain 2 instead of domain 1, because the backend cannot write cookies across domains (nginx reverse proxy can be implemented),
             *However, as long as the cookie authentication is written once in domain2, the following cross domain interfaces can obtain cookies from domain2, so that all interfaces can be accessed across domains
             */
            'Set-Cookie': 'l=a123456; Path=/; Domain=www.domain2. com; Httponly '// the purpose of httponly is to make JS unable to read cookies
        });

        res.write(JSON.stringify(postData));
        res.end();
    });
});

server.listen('8080');
console.log('Server is running at port 8080...');

7、 Nginx proxy cross domain

1. Nginx configuration solves iconfont cross domain

The browser’s cross domain access to JS, CSS, IMG and other conventional static resources is permitted by the same origin policy, with the exception of iconfont font file (eot|otf|ttf|woff|svg). 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

Homology policy is the security policy of the browser, not a part of HTTP protocol. When the server calls the HTTP interface, it only uses the HTTP protocol, does not execute JS scripts, does not need the homology strategy, and there is no crossing problem.

Realization idea

Configure a proxy server through nginx (the domain name is the same as domain1 and the port is different) as a springboard machine. The reverse proxy accesses the domain2 interface, and can modify the domain information in the cookie to facilitate the writing of the current domain cookie and realize cross domain login.

Nginx specific configuration

#Proxy server
server {
    listen       81;
    server_name  www.domain1.com;

    location / {
        proxy_ pass    http://localhost:8080 # Reverse proxy
        proxy_ cookie_ domain www.domain2. com www.domain1. com; # Modify the domain name in the cookie
        index  index.html index.htm;

        #When using middleware proxy interfaces such as webpack dev server to access nignx, there is no browser participation at this time, so there is no homology restriction. The following cross domain configuration can not be enabled
        add_ header Access-Control-Allow-Origin  http://www.domain1.com # When the current end only crosses domains without cookies, it can be*
        add_header Access-Control-Allow-Credentials true;
    }
}

Front end code example

var xhr = new XMLHttpRequest();

//Front end switch: whether the browser reads or writes cookies
xhr.withCredentials = true;

//Access the proxy server in nginx
xhr.open('get', 'http://www.domain1.com:81/?user=admin', true);
xhr.send();

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
    res.writeHead(200, {
        'Set-Cookie': 'l=a123456; Path=/; Domain=www.domain2. com; Httponly '// httponly: script cannot be read
    });

    res.write(JSON.stringify(params));
    res.end();
});

server.listen('8080');
console.log('Server is running at port 8080...');

8、 Nodejs middleware agent cross domain

Node middleware implements cross domain proxy. The principle is roughly the same as nginx. It realizes data forwarding by starting a proxy server. It can also modify the domain name in the cookie in the response header by setting the cookie domainrewrite parameter to write the cookie in the current domain to facilitate interface login and authentication.

8.1 cross domain of non Vue framework (twice cross domain)

Use node + Express + HTTP proxy middleware to build a proxy server.

8.1.1 front end code example:

var xhr = new XMLHttpRequest();

//Front end switch: whether the browser reads or writes cookies
xhr.withCredentials = true;

//Access HTTP proxy middleware proxy server
xhr.open('get', 'http://www.domain1.com:3000/login?user=admin', true);
xhr.send();

8.1.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://localhost:8080',
    changeOrigin: true,

    //Modify the response header information to realize 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 information
    cookieDomainRewrite: 'www.domain1. Com '// can be false, indicating no modification
}));

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

8.1.3 the background of nodejs is the same as (VI: nginx)

8.2 cross domain of Vue framework (one cross domain)

Use node + webpack + webpack dev server proxy interface to cross domain. In the development environment, since Vue rendering service and interface proxy service are the same as webpack dev server, there is no need to set header cross domain information between page and proxy interface.

webpack. config. JS part configuration:

module.exports = {
    entry: {},
    module: {},
    ...
    devServer: {
        historyApiFallback: true,
        proxy: [{
            context: '/login',
            target: ' http://localhost:8080 ', // proxy cross domain target interface
            changeOrigin: true,
            Secure: false, // used when the proxy reports an error on some HTTPS services
            cookieDomainRewrite: 'www.domain1. Com '// can be false, indicating no modification
        }],
        noInfo: true
    }
}

9、 Websocket protocol cross domain

Websocket protocol is a new protocol of HTML5. It realizes 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 inconvenient to use. We use socket IO, which well encapsulates the websocket interface, provides a simpler and more flexible interface, and provides downward compatibility for browsers that do not support websocket.

Front end code:

<div>user input:<input type="text"></div>
<script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script>
<script>
var socket = io('http://localhost:8080');

//Connection successfully processed
socket.on('connect', function() {
    //Listen for server messages
    socket.on('message', function(msg) {
        console.log('data from server: ---> ' + msg); 
    });

    //Monitor server shutdown
    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 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) {
        client.send('hello:' + msg);
        console.log('data from client: ---> ' + msg);
    });

    //Disconnect processing
    client.on('disconnect', function() {
        console.log('Client socket has closed.'); 
    });
});

last

Welcome to my official account, front end technology station.
replyreact:
1、React. JS public comment case full version
2. React + typescript high imitation ant design to develop enterprise UI component library
3. React17 + reacthook + ts4 best practice imitation JIRA enterprise project
replyvue
1. [full stack development] Vue + Django rest framework to build fresh e-commerce project
2. Core source code internal reference
3. Vue3 + elementplus + koa2 full stack development background system
4. ES6 zero foundation teaching analysis lottery
5、Node. JS + koa2 framework ecological practice – simulate Sina Weibo from zero (full version)
6. Vue unmanned ordering cashier system
replynode
1. Nodejs video tutorial
2. The last kilometer of the whole stack – online server deployment and release of nodejs project
3. Explain node in simple terms js

diary

Author: front end technology post station
Link:https://www.jianshu.com/p/93f2ed8c4dc7
Source: developeppaper
The copyright belongs to the author. For commercial reprint, please contact the author for authorization. For non-commercial reprint, please indicate the source.