Causes and solutions of cross domain problems

Posted by cybercookie72 on Sat, 29 Jan 2022 18:15:30 +0100

1, What is cross domain?

In the front-end field, cross domain refers to that the browser allows to send cross domain requests to the server, so as to overcome the limitation that Ajax can only be used in the same source.

When cross domain, you will receive the following error

2, What is homology strategy?

Homology policy is an agreement. The browser was introduced by Netscape in 1995. It is the most core and basic security function of the browser. Without homology policy, the browser is vulnerable to XSS, CSFR and other attacks. 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.

URL composition:

 

The same origin policy limits the following behaviors:

  • Cookie s, LocalStorage and IndexDB cannot be read
  • DOM and JS objects cannot be obtained
  • AJAX request cannot be sent

3, Solution
1.JSONP cross domain

Principle: there is no cross domain restriction on the < script > tag. Through the src attribute of the < script > tag, send a GET request with callback parameters. The server will piece the interface return data into the callback function and return it to the browser. The browser will parse and execute it, so that the front end can GET the data returned by the callback function.

Disadvantages: only one request can be sent.

realization:

1) Native JS implementation:

 <script>
    var script = document.createElement('script');
    script.type = 'text/javascript';

    // Pass a callback function name to the back end to facilitate the execution of the callback function defined in the front end when the back end returns
    script.src = 'http://www.domain2.com:8080/login?user=admin&callback=handleCallback';
    document.head.appendChild(script);

    // Callback execution function
    function handleCallback(res) {
        alert(JSON.stringify(res));
    }
 </script>

The server returns the following (execute the global function when returning):

handleCallback({"success": true, "user": "admin"})

jquery Ajax implementation:

$.ajax({
    url: 'http://www.domain2.com:8080/login',
    type: 'get',
    dataType: 'jsonp',  // The request method is jsonp
    jsonpCallback: "handleCallback",  // Custom callback function name
    data: {}
});

Vue axios implementation:

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

Backend node JS code:

var querystring = require('querystring');
var http = require('http');
var server = http.createServer();

server.on('request', function(req, res) {
    var params = querystring.parse(req.url.split('?')[1]);
    var fn = params.callback;

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

2. Cross domain resource sharing (CORS)

CORS is a W3C standard, whose full name is "cross origin resource sharing".
It allows browsers to send XMLHttpRequest requests to cross source servers, thus overcoming the limitation that AJAX can only be used in the same source.
CORS requires both browser and server support. At present, all browsers support this function, and IE browser cannot be lower than IE10.
The browser divides CORS cross domain requests into simple requests and non simple requests.
As long as the following two conditions are met at the same time, it is a simple request

(1) Use one of the following methods:

    head
    get
    post

(2) The requested Heder is

    Accept
    Accept-Language
    Content-Language
Content type: limited to three values: application/x-www-form-urlencoded, multipart / form data, text/plain

If the above two conditions are not met at the same time, it is a non simple request. The browser handles these two types differently.

Simple request

For simple requests, the browser directly sends CORS requests. Specifically, add an Origin field to the header information.

GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

In the header information above, the Origin field is used to indicate which source the request comes from (protocol + domain name + port). Based on this value, the server decides whether to agree to the request.

CORS cross domain example

Native ajax:

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

// Front end setting whether to bring cookie s
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);
    }
};

jquery ajax:

$.ajax({
    ...
   xhrFields: {
       withCredentials: true    // Front end setting whether to bring cookie s
   },
   crossDomain: true,   // It will make the request header contain additional information across domains, but will not contain cookie s
    ...
});

3.nginx proxy cross domain

nginx proxy cross domain is essentially the same as CORS cross domain principle. It sets the request response header access control allow origin... And other fields through the configuration file.

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

nginx reverse proxy interface Cross Domain

Cross domain problem: the same origin policy is only a security policy for browsers. When the server calls the HTTP interface, it only uses the HTTP protocol, does not need the homology strategy, and there is no cross domain problem.

Implementation 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 access.
Specific configuration of nginx:

#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; #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 cookie s, it can be*
        add_header Access-Control-Allow-Credentials true;
    }
}

5.document.domain + iframe cross domain

This method can only be used when the secondary domain name is the same, such as a.test COM and b.test Com applies to this method. You just need to add document. XML to the page domain ='test. 'com' means that if the secondary domain names are the same, cross domain can be realized.

www.   baidu.  com     .
Tertiary domain secondary domain top-level domain root domain

Implementation principle: both pages are forced to set document. XML through js Domain as the basic primary domain, the same domain is realized.

example:

Parent window: (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>

Child window: (child.domain.com/a.html)

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

6.location.hash + iframe cross domain

Implementation principle: if a wants to communicate with b across domains, it is realized 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.

Specific 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: (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 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: (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 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: (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>

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

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.

a.html: (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);
    }
};

// Request cross domain b page data
proxy('http://www.domain2.com/b.html', function(data){
    alert(data);
});

proxy.html: (www.domain1.com/proxy.html)

The intermediate agent page has the same domain as a.html, and the content can be empty.

b.html: (www.domain2.com/b.html)

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

 8.postMessage cross domain

postMessage
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:

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

otherWindow.postMessage(message, targetOrigin, [transfer]);

    1

otherWindow: a reference to other windows, such as iframe's contentWindow attribute and execution window The window object returned by open, or a named or numerically indexed window frames.
message: data to be sent to other window s.
targetOrigin: specify which windows can receive message events through the origin attribute of the window
Transfer (optional): a string of Transferable objects that are passed simultaneously with message Ownership of these objects will be transferred to the receiver of the message, and the sender will no longer retain ownership

example:
a.html: (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'
        };
        // 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: (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>

9.WebSocket protocol cross domain

Principle: this method essentially does not use the HTTP response header, so there is no cross domain restriction.

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.
Establish a "socket" connection between the web browser and the server. Simply put: there is a persistent connection between the client and the server, and both sides can start sending data at any time.
--------
Front end code:

<script>
  let socket = new WebSocket("ws://localhost:8080");
  socket.onopen = function() {
    socket.send("holle");
  };
  socket.onmessage = function(e) {
    console.log(e.data);
  };
</script>


--------
Backend code:

const WebSocket = require("ws");
const server = new WebSocket.Server({ port: 8080 });
server.on("connection", function(socket) {
  socket.on("message", function(data) {
    socket.send(data);
  });
});

10. Open cross domain browser

In fact, the cross domain problem is the browser strategy. The source is him. Turn off this function

Windows
Find the directory where you installed

.\Google\Chrome\Application\chrome.exe --disable-web-security --user-data-dir=xxxx

Mac
~/The directory downloads / Chrome data can be customized

/Applications/Google\ Chrome\ Canary.app/Contents/MacOS/Google\ Chrome\ Canary  --disable-web-security --user-data-dir=~/Downloads/chrome-data

4, What is the homology strategy against

Cross domain only exists on the browser side. The browser provides access to the web. We can open many pages in the browser. It is such an open form, so we need to limit it. For example, when the forest is large and there are all kinds of birds, we need to have a unified specification to make an agreement in order to ensure this safety.

Restrict requests from different sources and prevent various requests of JavaScript code for non source pages (CSRF attack)
For example, when a user logs in to website a and a new tab opens website b, if the homology is not limited, b can make any request like website a, which will give criminals an opportunity to take advantage of it.
Restrict DOM operations and read DOM elements of other pages (usually containing sensitive information, such as input tags)
Phishing website
--------
5, Summary

jsonp (only supports get requests and old IE browsers) is suitable for loading static resources such as js, css and img of different domain names;
CORS (supports all types of HTTP requests, but not for browsers below IE10) is suitable for ajax cross domain requests;
The cross domain principle of Nginx proxy is similar to that of nodejs middleware. They both build a server and directly request the HTTP interface on the server side, which is suitable for the front-end and back-end interfaces of front-end projects separated from front-end and back-end projects.
document.domain+iframe is suitable for cross domain requests with the same primary domain name and different subdomains.
postMessage and websocket are new features of HTML5, and their compatibility is not very good. They are only applicable to mainstream browsers and IE10 +.
--------

Topics: Javascript Ajax jsonp