Cross domain

What is cross-domain

URI format:

scheme://+user:passwd@+host:port+path+? query+#fragment

Browsers follow the same origin policy:

If the scheme, host, and port are all the same, it is the same source.

Non-homologous restriction:

  1. Cannot read or modify each other’s DOM
  2. Do not read and access each other’s cookies, IndexDB, and LocalStorage
  3. Restricts XMLHttpRequest requests

Tags that allow cross-domain loading of resources:

, ,

  • Cross-domain is identified only by scheme(protocol), host(host), and port(port), and is not determined by whether the IP addresses corresponding to domain names are the same.

  • If protocols and ports cause cross-domain problems, the front-end cannot resolve them.

  • Responses to cross-domain requests are typically blocked by browsers.

Cross-domain requests can be made using forms, so why not Ajax? Because ultimately, cross-domain is about preventing the user from reading content under another domain name, Ajax can get a response that the browser considers unsafe, so it blocks the response. But the form doesn’t get new content, so it can make a cross-domain request. It also shows that cross-domain does not prevent CSRF completely, because the request is made after all.

How to solve cross-domain problems

CORS and Nginx reverse proxy are common cross-domain solutions in practice, JSONP needs to understand, other methods do not expand in detail.

CORS

CORS is a W3C standard, which stands for “Cross-origin Resource Sharing”. It needs to be supported by both the browser and the server. The server needs to add the Access-Control-Allow-Origin response header,

Compatibility: Non-INTERNET Explorer and IE 10 or later support CORS. Internet Explorer 8/9 requires XDomainRequest.

Advantages: Support for all types of request methods.

Browsers classify simple requests and non-simple requests (complex requests) based on the request method and specific fields in the request header.

Simple requests that meet the following conditions are classified as non-simple requests:

  1. There are three request methods: GET, POST, and HEAD
  2. The values of the request header Accept, accept-language, content-language, and Content-Type are as follows:application/x-www-form-urlencoded,multipart/form-data,text/plain

A simple request

The browser automatically adds the Origin field to the request header of a simple request to indicate which source the request is from. The server adds the Access-Control-allow-Origin field to the response header to list the sources that Allow cross-domain requests. A value of * indicates that all sources are allowed. If Origin is not in the range of Access-Control-Allow-Origin, the browser intercepts the response.

The following fields set the specific functionality that will be blocked if it is:

Access-Control-Allow-Credentials

Boolean value that indicates whether cookies, Authorization Headers, or TLS client certificates of the response can be exposed to the page. The default value is false.

For cross-domain requests, if you need to retrieve the browser’s Cookie, you need to add this response header and set it to true, and you need to set the withCredentials property on the front end:

let xhr = new XMLHttpRequest();
xhr.withCredentials = true;
Copy the code

ccess-Control-Expose-Headers

Values are set in the format
,
,… The response header field lists which headers can be exposed as part of the response.

By default, only seven simple Response headers can be exposed to the outside world:

Cache-control, Content-language, Content-Length, Content-Type, Expires, Last-Modified, Pragma

If you want to make other Headers accessible to the client, you can list them in access-Control-expose-headers.

Non-simple request

  1. Before formal communication, non-simple requests add an HTTP query request, called a precheck request. Precheck initiates an OPTIONS request to know whether the server allows cross-domain requests.

  2. The precheck Request header contains the Origin source address, the Host destination address, and the access-Control-request-method HTTP Method that the CORS Request will use. Access-control-request-headers Specifies the Request Headers to be added to the CORS Request.

  3. The response header of the pre-check request contains access-Control-allow-origin, access-Control-allow-methods, access-Control-allow-credentials, and access-Control-allo W-headers, access-Control-max-age (validity period of the pre-check request, within which no pre-check request is initiated).

  4. If the precheck request response does not meet the condition, the onError method of XMLHttpRequest will be raised. The actual CORS request will not be initiated. If the condition is met, the browser automatically adds the Origin field to the CORS request. The server response header returns access-Control-allow-Origin.

JSONP

The principle of JSONP is simple: it uses

Advantages: Good compatibility.

Disadvantages: Only support GET method, insecure, may be subject to XSS attacks.

The difference between JSONP and AJAX: JSONP is a non-same-origin policy for cross-domain requests, while AJAX is a same-origin policy.

Encapsulate a JSONP

var jsonp = ({ url, params, callbackName }) = > {
    var generateURL = () = > {
        let arrs = [];
        for(let key in params) {
            arrs.push(`${key}=${params[key]}`);
        }
        arrs.push(`callback=${callbackName}`); // The parameter passed to the back end is called callback
        return `${url}?${arrs.join('&')}`;
    };
    return new Promise((resolve, reject) = > {
        callbackName = callbackName || Math.random().toString().replace('. '.' '); 
        // Create the script tag
        let _script = document.createElement('script');
        _script.src = generateURL();
        document.body.appendChild(_script);
        // Bind callback to window object
        window[callbackName] = (data) = > {
            resolve(data);
            // Clear the script tag
            document.body.removeChild(_script); }}); }Copy the code

use

jsonp({
    url: 'http://localhost:3000'.params: { say: 'hello' },
    callbackName: 'sayhi'
}).then(data= > {
    console.log('hi,',data)
})
Copy the code

The back-end

let express = require('express')
let app = express()
app.get('/'.function(req, res) {
  let { say, callback } = req.query
  console.log(say); // hello
  console.log(callback); // sayhi
  // The browser executes the string returned to script directly
  res.end(`${callback}('jiuto')`);
})
app.listen(3000)
Copy the code

Nginx reverse proxy

Reverse proxy A reverse proxy server is configured to receive requests from clients and forward requests to other servers. The reverse proxy server is used to maintain load balancing of server clusters.

Advantages: only need to modify nginx configuration, support all browsers, support session, do not need to modify the code, does not affect the server performance.

server {
  listen  80; server_name client.com; location /api { proxy_pass server.com; }}Copy the code

Nginx acts as a leapfrog, whose domain name is also client.com, allowing clients to first visit client.com/api, which of course is not cross-domain, and then the Nginx server acts as a reverse proxy, forwarding requests to server.com. When the response is returned, it is sent back to the client, completing the entire cross-domain request process.

Other methods

May refer toCommon Cross-domain solutions at the front end (full),Nine Cross-domain Implementation Principles (Full version)

  • Node middleware proxy (cross domain twice)

  • postMessage

  • websocket

  • window.name + iframe

  • location.hash + iframe

  • document.domain + iframe

reference

Nine Cross-domain Implementation Principles (Full version)

014: What is cross-domain? How does the browser intercept the response? How to solve it?