Cross domain solutions

Posted by matbennett on Wed, 05 Jan 2022 08:39:36 +0100

Cross domain

  • The principle of cross domain is: the same domain is only when the protocol, domain name and port are the same. Otherwise, it is cross domain. Cross domain means that the browser does not allow the source of the current page to request data from another source

Homology
Another concept is homology. Homology refers to the same protocol, port and domain name.

The Same origin policy is a convention. It is the core and basic security function of the browser. If the Same origin policy is missing, the normal functions of the browser may be affected. It can be said that the Web is built on the Same origin policy, and the browser is only an implementation of the Same origin policy.

The same origin policy is in consideration of user security. If it is not the same origin, it will be subject to the following restrictions:

  • The cookie cannot be read
  • dom cannot get
  • ajax requests cannot be sent

However, the fact is that it is often necessary to provide data with the help of non homologous sources, so cross domain requests are required.

JSONP
JSONP refers to JSON Padding. JSONP is an unofficial cross domain data exchange protocol. Because the src attribute of script can be requested across domains, JSONP takes advantage of this "vulnerability" of the browser. When communication is needed, a script tag is dynamically inserted. The requested address usually has a callback parameter. It is assumed that the address to be requested is http://localhost:666?callback=show , the code returned by the server is generally the JSON data of show (data), and the show function is exactly the function that the foreground needs to use this data. JSONP is very simple and easy to use. The automatic completion API uses JSONP. Here is an example:

// Front end request code
function jsonp (callback) {
    var script = document.createElement("script"),
        url = `http://localhost:666?callback=${callback}`;
    script.setAttribute("src", url);
    document.querySelector("head").appendChild(script);
}
function show (data) {
    console.log(`Student Name: ${data.name},Age: ${data.age},Gender ${data.sex}`);
}
jsonp("show");
// Back end response code
const student = {
    name: "zp1996",
    age: 20,
    sex: "male"
};
var callback = url.parse(req.url, true).query.callback;
res.writeHead(200, {
    "Content-Type": "application/json;charset=utf-8"
});
res.end(`${callback}(${JSON.stringify(student)})`);
  • Although JSONP is simple and easy to use, there is a big problem, that is, JSONP can only make get requests

CORS
cors is the mainstream cross domain solution. Cross domain resource sharing (CORS) is a mechanism that uses additional HTTP headers to tell browsers that Web applications running on an origin (domain) are allowed to access specified resources from different source servers. When a resource requests a resource from a domain, protocol or port different from the server where the resource itself is located, the resource will initiate a cross domain HTTP request.

  • The request method is GET or POST
  • If the request is POST, the content type must be one of the following:
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain
  • Does not contain a custom header (similar to the X-Hit header customized by segmentfault)
    For cross domain simple requests, only one http request is required:
function ajaxPost (url, obj, header) {
    return new Promise((resolve, reject) => {
        var xhr = new XMLHttpRequest(),
        str = '',
        keys = Object.keys(obj);
      for (var i = 0, len = keys.length; i < len; i++) {
        str += `${keys[i]}=${obj[keys[i]]}&`;
      }
      str = str.substring(0, str.length - 1);
      xhr.open('post', url);
      xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
      if (header instanceof Object) {
        for (var k in header) 
            xhr.setRequestHeader(k, header[k]);
      }
      xhr.send(str);
      xhr.onreadystatechange = function () {
        if (xhr.readyState === 4) {
          if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
            resolve(xhr.responseText);
          } else {
            reject();
          }
        }
      }
    });
}
ajaxPost("http://localhost:666?page=cors", {
    name: "zp1996",
    age: 20,
    sex: "male"
})
.then((text) => { console.log(text); }, 
            () => { console.log("request was aborted"); });

// Back end processing
var postData = "";
// Note, the following example background code is supplemented here
req.on("data", (data) => {
    postData += data;
});
req.on("end", () => {
    postData = querystring.parse(postData);
    res.writeHead(200, {
        "Access-Control-Allow-Origin": "*",
        "Content-Type": "application/json;charset=utf-8"
    });
    if (postData.name === student.name &&
        Number(postData.age) === student.age &&
        postData.sex === student.sex
         ) {
        res.end(`yeah!${postData.name} is a good boy~`);
    } else {
        res.end("No!a bad boy~");
    }
});


  • vue proxy cross domain: request the local server, then the local server requests the remote server (the server with the back-end deployment interface), and finally the local server returns the requested data to the browser (there is no cross domain between the local server and the browser)

Two key points:
There is no cross domain between the local server (proxy using the local server created by node.js, also known as proxy server) and the browser
There is no cross domain between server and server

First create a Vue config. JS file

// Suppose the interface to be requested is: http://40.00.100.100:3002/api/user/add
module.exports = {
    devServer:{
      host:'localhost',  // Local host
        port:5000,  // Port number configuration
        open:true,  // Open browser automatically
        proxy:{
          '/api': {   //  Intercept interfaces starting with / api
            target: 'http://40.00. 100.100:3002 ', / / set the domain name and port number of the interface you call. Don't forget to add http
            changeOrigin: true,    //Here, true means cross domain implementation
            secure: false, // If it is an https interface, this parameter needs to be configured
            pathRewrite: {
              '^/api':'/'  //It is understood here that '/ API' is used to replace the address in the target. In the later components, when we drop the interface, we directly use API instead. For example, I want to call ' http://40.00.100.100:3002/api/user/add , just write '/ API / user / add'
            }
          },
    // If another interface is: http://40.00.100.100:3002/get/list/add
    // Then configure another get, as follows:
          '/get': {   //  Intercept interfaces starting with / get
            target: 'http://40.00. 100.100:3002 ', / / set the domain name and port number of the interface you call. Don't forget to add http
            changeOrigin: true,    //Here, true means cross domain implementation
            secure: false, // If it is an https interface, this parameter needs to be configured
            pathRewrite: {
              '^/api':'/'  //It is understood here that '/ api' is used instead of the address in the target,
            }
          }
			// You can call / get/list/add directly
        }
    }
  }

  // Note: after modifying the configuration file, you must restart it to take effect;


We can use the baseUrl of axios, and the default value is api. In this way, we will automatically fill in the api prefix every time we visit, so we don't need to write this prefix on each interface manually
The configuration in the entry file is as follows:

import axios from 'axios'

Vue.prototype.$http = axios
axios.defaults.baseURL = 'api'  // Later, I found that it seems OK not to add this feeling

If this configuration 'api/' The local domain is read by default

If it's just development environment testing, the above one is enough if you distinguish between production and development environments
The following configuration is required

Cross domain configuration by environment: create an API config. JS file (in fact, you can name it casually)

const isPro = Object.is(process.env.NODE_ENV, 'production')
// If it is a production environment, use the online interface;
module.exports = {
    baseUrl: isPro ? 'http://www.vnshop.cn/api/' : 'api/'
}

After the above configuration, the dom can be accessed easily, and there is no need to introduce the axios module into any component

 async getData(){
        const res = await this.$http.get('/api/user/add');
        console.log(res);
    },

The main way of proxy cross domain is to avoid cross domain problems by using the way of server requesting server.General process: browser===>proxy server ===>Target server.

Topics: Javascript Front-end http