Front end cross domain solution

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.

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.

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

2, Cross domain solutions

jsonp

The principle of jsonp is to use the src attribute of < script > tag without cross domain restrictions to send a GET request with callback parameters. The server will piece up the interface return data into the callback function and return it to the browser. The browser will analyze and execute it, so that the front end can GET the data returned by the callback function.

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 as follows (execute the global function when returning)

// The string returned by the server is executed as js code at the front end
handleCallback({"success": true, "user": "admin"})

2. Implementation of jquery ajax

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

3. 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) + ')');	// fn(params)

    res.end();
});

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

Disadvantages of jsonp:

  • Only one request can be sent
  • Server support is required

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.

The response header fields of CORS request settings start with access control -:

  • 1) Access control allow origin: required

    Its value is either the value of the Origin field at the time of the request or a *, indicating that the request for any domain name is accepted.

  • 2) Access control allow credentials: optional

    Its value is a Boolean value indicating whether cookies are allowed to be sent. By default, cookies are not included in CORS requests. If it is set to true, it means that the server has explicit permission. Cookie s can be included in the request and sent to the server together. This value can only be set to true. If the server does not want the browser to send cookies, delete this field.

  • 3) Access control expose headers: optional

    When CORS requests, the getResponseHeader() method of XMLHttpRequest object can only get six basic fields: cache control, content language, content type, Expires, last modified and Pragma. If you want to get other fields, you must specify them in access control expose headers.

Non simple request

Non simple requests are those that have special requirements for the server. For example, the request method is PUT or DELETE, or the type of content type field is application/json. For CORS requests that are not simple requests, an HTTP query request will be added before formal communication, which is called "preflight".

Pre inspection request

The request method used in the "pre check" request is OPTIONS, which indicates that the request is used for inquiry. In the request header information, the key field is Origin, which indicates the source of the request. In addition to the Origin field, the "pre check" request header information includes two special fields.

OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0..
  • 1) Access control request method: required
    It is used to list the HTTP methods used by the browser's CORS request. The above example is PUT.

  • 2) Access control request headers: optional
    This field is a comma separated string that specifies the header information field that the browser CORS request will send additionally. The above example is x-custom header.

Response to pre inspection request

After receiving the "pre check" request, the server checks the Origin, access control request method and access control request headers fields and confirms that cross source requests are allowed to respond.

In the HTTP response, in addition to the key access control allow origin field, other CORS related fields are as follows:

  • 1) Access control allow methods: required

    Its value is a comma separated string indicating all cross domain request methods supported by the server. Note that all supported methods are returned, not just the one requested by the browser. This is to avoid multiple "pre check" requests.

  • 2)Access-Control-Allow-Headers

    If the browser request includes an access control request headers field, the access control allow headers field is required. It is also a comma separated string, indicating all header information fields supported by the server, not limited to the fields requested by the browser in "pre check".

  • 3) Access control allow credentials: optional

    This field has the same meaning as simple request. Whether cookies are allowed to be carried across domains. If the access control allow origin field is *, cookies can no longer be carried

  • 4) Access control Max age: optional

    Used to specify the validity period of this pre inspection request, in seconds.

golang code example

func (base *DateMethod) method(w http.ResponseWriter, r *http.Request, allowOrigin string, contentType int, authencation string) (http.ResponseWriter, *http.Request, bool) {
	err := true
	w.Header().Set("Content-Security-Policy", "upgrade-insecure-requests")
	w.Header().Set("Access-Control-Allow-Origin", allowOrigin) //Allow access to domain
	// Print log request URL and request method
	mylog.Println(r.URL.String(), r.Method)
	if r.Method == "OPTIONS" { // Pre inspection request
		w.Header().Set("Access-Control-Allow-Credentials", "true")                                                   // Allow sending cookie s
		w.Header().Set("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authencation, Token") // Additional fields allowed to send
		w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, PATCH, DELETE")
		w.Header().Set("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
		err = false
	} else {
		if authencation != "" {
			if r.Header.Get("Authencation") != authencation {
				w.WriteHeader(407)
				err = false
			}
		}
		if contentType == 1 {
			w.Header().Set("content-type", "application/json")
		}
	}
	return w, r, err
}

CORS cross domain example

1) Front end settings

$.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
    ...
});

2) Server settings

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 proxy can write cookie s across domain 1 instead of domain 2,
             * 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'  // HttpOnly is used to make js unable to read cookie s
        });

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

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

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.

Cross domain of non vue framework

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

Front end code

var xhr = new XMLHttpRequest();

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

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

Middleware server code

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 realize cross domain and allow cookie s
    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'  // It can be false, indicating that it is not modified
}));

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

Cross domain of vue framework

Webp-server + webp-dev config. JS configuration. In the development environment, vue rendering service and interface proxy service are the same as webpack dev server, so there is no cross domain between page and proxy interface.

webpack.config.js partial configuration

module.exports = {
    entry: {},
    module: {},
    ...
    devServer: {
        historyApiFallback: true,
        // proxy: [{
        //    context: '/login',
        //    target: 'http://www.domain2.com: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
        // }],
        proxy: {
			'/': {	// All requests starting with / will be transferred to target for request
				// For example, axios sends a request with a request path of / login. The default request is http://127.0.0.1:3000/login
				target: 'http://127.0.0.1:3000',
				changeOrigin: true
			}
		}
        noInfo: true
    }
}

Keywords: Javascript node.js Vue

Added by argoSquirrel on Fri, 04 Mar 2022 06:35:35 +0200