What is a cross-domain problem

When a browser requests resources of a domain name from a web page of another domain name, the domain name, port, or protocol are all different

Cross domain cross domain, see name know meaning, cross domain meaning. So what is a domain?

We know that in order for either front-end or back-end code to run, it needs to be supported by a service, that is, an IP (host) address and a port on that IP (host). An IP plus port is the domain of a service (HTTP or HTTPS must be consistent, otherwise it will cross domains).

And development project at present is mainly separation practice before and after the end, the start up front a front-end services (front themselves with a TCP/IP port), start up the backend a back-end services (backend also have their own IP port) need what data resources, send a request to the backend, back-end, after receipt of a request from the database query data, You get the result and you feed it back to the front end. As a result, there is the problem of the front end going out of its domain to the back end to ask for data. However, there is a sacred rule in browsers: the same origin policy rule. The same origin policy rule detects that a request has crossed the domain, and immediately blocks the request, as well as notifies the developer of an error. So, what is the same origin policy rule?

Same origin policy rule

Same-origin_policy refers to the Same source (domain name, port, and protocol). This is a very important security strategy, stratagem. Currently, almost all browsers follow the same origin policy, which states:

  1. Non-cognate browser requests and responses cannot share cookies, LocalStorage, IndexDB, etc
  2. Non-homologous, DOM and Js objects are not available
  3. Non-homologous, AJAX requests are disabled

We can see that the same origin policy also restricts a lot of operations, can not get cookies, LocalStorage, DOM, Js objects and Ajax requests are also restricted to send, so it is much safer. Especially for banks and financial institutions. The knowledge of network security (XSS, CSRF, SQL injection attacks, Dos attacks, etc.) is not needed here, just remember that the more strict rules and regulations, the safer for users. That’s why the same origin policy has been added to browsers.

But the same origin policy security is safe, we have a little trouble developing the project. Ajax requests are disabled, so the front and back interfaces can’t be synced, so we need to solve the same origin policy cross-domain issues

Small history: In 1995, Netscape introduced the same origin policy into the browser as a core security feature to protect against XSS, CSFR and other attacks.

Documentation on the official website of the same Origin policy: developer.mozilla.org/zh-CN/docs/…

Present cross-domain problems

Before we solve the cross-domain problem, let’s present the cross-domain problem. Let’s see what it looks like across domains, so in this case, let’s make the front and back end services have different IP addresses and different ports. See

The back-end code

The IP address of the computer used by the backend is 10.9.26.107 and the port is 4000, so the domain of the backend is http://10.9.26.107:4000/

const http = require('http');// Introduce the HTTP module

const port = 4000;// Set a port

const server = http.createServer((req, res) = > { // Create a service to return data
    res.statusCode = 200;
    res.setHeader("Content-type"."application/json");
    res.end('Hello, cross domain.');
});

server.listen(port, () = > { // Start the service on port 4000 and listen
    console.log(`server running at ${port}/ `);
});
Copy the code

The front-end code

Here we use the Vue framework, plus the AXIos library, to be faster and more efficient. As for the front-end IP port address (domain), the default native port is used: http://localhost:8080/

<template>
  <div id="box">
    <el-button @click="crossDomain">Cross-domain emerge</el-button>
  </div>
</template>

<script>
const axios = require('axios'); // Introduce the AXIos library
export default {
  methods: {
    crossDomain(){
      axios.get('http://10.9.26.107:4000/') // Make a request to the back-end service
      .then((res) = >{
        console.log('Request result',res);
      })
      .catch((err) = >{
        console.log('error',err); })}}};</script>
Copy the code

Here our request is: from http://localhost:8080/ domain to http://10.9.26.107:4000/, IP and port are different, of course, HTTP protocol is the same. So you’re constrained by the same origin policy, and you have cross-domain problems

Cross-domain problems occur

This error occurs when we click the “Cross domain Emerge” button, both network and console

Translation:

XMLHttp requests sent from the local localhost:8080 location to http://10.9.26.107:4000/ are disallowed by CORS policy, missing access-Control-allow-Origin headers

This is the presentation of common cross-domain problems in work. If there are problems, they need to be solved. How do we solve them? Let’s read on…

Use CORS to solve cross-domain problems

Introduction of CORS

Cross-source resource sharing (CORS) is a W3C solution to the cross-domain same-origin policy (it was proposed because there was no good solution), and the console suggested using CORS to solve this problem in the case above. With this setting, you can solve the problem of cross-domain access prohibition. Cors is widely used because of its simplicity and ease of use

Official address: developer.mozilla.org/zh-CN/docs/…

Cors solves cross-domain problems

Res.setheader (” access-Control-allow-origin “,”*”); res.setheader (” access-Control-allow-origin “,”*”); res.setheader (” access-Control-allow-origin “,”*”); Because the asterisk * means everything; If you want to specify a url, replace the asterisk with the corresponding url.

The key codes are as follows:

const server = http.createServer((req, res) = > {
    res.statusCode = 200;
    res.setHeader("Access-Control-Allow-Origin"."*"); // All cross-domain requests are allowed, with the * asterisk indicating all
    res.setHeader("Content-type"."application/json");
    res.end('Hello, cross domain.');
});
Copy the code

Of course, cORS is written in various ways and plays a great role. In practical development, we can write as follows:

 // The allowed header type
 res.header("Access-Control-Allow-Headers"."content-type");
 // The type of requests that are allowed across domains
 res.header("Access-Control-Allow-Methods"."DELETE,PUT,POST,GET,OPTIONS");
/ / and so on...
Copy the code

Attach detailed points on www.w3cschool.cn/javascript_…

The CORS solution is a little more concise and convenient, so I don’t have much space, but let’s take a look at the older cross-domain solution: JSONP

Cross domain resolution using JSONP

What is the json

JSONP(JSON with Padding) is an unofficial cross-domain solution that relies purely on the ingenuity of programmers, but is limited to support only GET requests. Post, PUT, delete requests are not supported. This method is rarely used in everyday work, but it’s important to know

How JSONP works

We know that in HTML tags, some tags are created to allow cross-domain access to resources (such as images, files, etc.) at a certain address. Such as img tags, link tags, iframe tags, script tags

JSONP uses the cross-domain capabilities of script tags to send requests.

Example of JSONP writing

Server code

const express = require('express')
const app = express()
// We use the Express framework to specify a port to return data to the front-end
app.get('/myServer'.(req, res) = > {
    res.end("hello JSONP")
})
app.listen(6789.() = > {
    console.log(The service has been started)})Copy the code

So the address of the server code to: http://localhost:6789/myServer

The front-end code

In the front-end HTML code, we use vscode editor and install the Live Server plug-in, so we right click to start the browser, and the final front-end code domain port is: http://127.0.0.1:5500/JSONP.html Live Server plug-in is the default port 5500. Comparing the domain ports of the front and back end services, we find that they are indeed cross-domain, so let’s see if JSONP can solve the cross-domain problem

<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
</head>
<body>
    <! -- Using the SRC attribute... -->
    <script src="http://localhost:6789/myServer"></script>
</body>
</html>
Copy the code

We specify the address of the server with the SRC attribute of the script tag, so when the browser loads the rendered page, it will request the address in SRC to get the data. When we open the Network panel in F12, we will see that the request was sent successfully and the data was received, but the console reported an error. Let’s take a look at the following two pictures, illustrated as follows:

Cross domain success request graph

The cross-domain problem appears to have been successfully resolved, but in fact, the cross-domain problem is only half resolved because the console reported an error, as shown in the following figure:

Cross – domain success console error icon

JSONP error cause

JSONP cannot return data directly. The browser cannot recognize the data directly. Because the script tag of the browser needs to be JS code, since we want JS code, we thought of giving the browser a function JS code, and passing the data that needs to be returned to the front end as parameters in the function to the front end, so that the browser can recognize. The front end only needs to declare a corresponding function to receive

In other words, JSOP needs to return the data as a parameter to the function, rather than returning the data directly, and the front end needs to declare a function of the same name to receive the data

So the correct way to write it is this

The correct way to write JSONP

The service side

app.get('/myServer'.(req, res) = > {
    let data = {
        name:"Sun Wukong".age:"500".home:"Water Curtain Cave of Huaguo Mountain"
    }
    let resData = JSON.stringify(data)
    res.end(`fn(${resData}) `)})Copy the code

The client

<body>
    <script>
        // The function name fn must be the same as the name defined at the back end so that it can be parsed
        // The corresponding function can be found in order to obtain the corresponding data
        function fn(data) {
            console.log(data);
        }
    </script>
    <script src="http://localhost:6789/myServer"></script>
</body>
Copy the code

JSONP front-end complete writing

Assuming we click JSONP to make a request, let’s look at the native code as follows:

<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
</head>
<body>
    <button>Send the request</button>
    <script>
        // The first step is to declare a function to receive the return from the back end
        function fn(data) {
            console.log('Data returned from the back end', data);
        }
        document.querySelector('button').onclick = function () {
            // Create a script tag
            let script = document.createElement("script")
            // Step 3, specify the address to send the request
            script.src = "http://localhost:6789/myServer"
            // Step 4, insert the label into the document
            document.body.appendChild(script)
        }
    </script>
</body>
</html>
Copy the code

So this is a simple example of using JSONP, but JSONP only supports GET requests, even though the advantage of JSONP is that it supports older browsers and can request data from sites that do not support CORS. In fact, if we think about it, it’s 2021, and basically the old browsers are gone. So JSONP is basically not used, but we need to know this thing as well

The article summarizes

  • CORS supports all types of HTTP requests and is the best solution across domains (back-end configuration required)
  • JSONP only supports GET requests. The advantage of JSONP is that it works in some old browsers. After all, old browsers do not have CORS rules (front-end writing, back-end with the definition of function name)

It can also be configured by means of Node proxy, such as the proxy object in devServer in the vue.config.js file in the Vue framework

Of course, it is also possible to use nginx reverse proxies to solve cross-domain problems.

Whether Node middleware proxy or Nginx reverse proxy, it is mainly through the same origin policy does not apply to the server to control, after all, the same origin policy is the browser rules, and the server has no relationship. On a daily basis, the dominant cross-domain solutions are CORS and NGINX reverse proxies