Same-origin policy:

  • Source: We can enter window.origin in the console of any web page to get the source of the current web page. Such as:

Source: ** protocol (HTTPS)+ domain name (www.tencent.com)+ port number (port 80 by default). ** So if two web pages have the same protocol, domain name, and port number, they are the same source.

  • ** Same-origin policy: If A JS is running in source A, it can only get data from the current source, and cannot get data from other sources. ** Here’s an example:

If we reference cdn.com/xx.js file in qq.com, xx.js can only obtain the data of the current source qq.com, xx.js is running in the source qq.com, so we can’t use it to obtain the data of www.tencent.com source. However, it is important to note that we are not importing js files as cross-domain access, because we are simply fetching js files and running them in our browser, not reading them.

  • Why to design same-origin policy:

We can think of a simple scenario, if we log in our QQ zone (using cookies), we send Ajax request through the source of qzone.qq.com to get the data in this source, namely our friend list, When someone else requests data from another source, let’s say xxx.com, the server will respond to the request and send back the data. The reason is that the server can’t distinguish between these two requests, the only difference is the referer, and if the server doesn’t check the referer, then our friend data will be stolen. So the bottom line is that the same origin policy protects our privacy.

Simulate cross-domain access:

Let’s experiment with an example of a browser blocking cross-domain access:

  • First we open a server through Node.js with port 8888.

  • There are three files in this server, index. HTML, qi. js and Friends. json. We introduce our qi. js in index, send Ajax request in qi. js to get friends.json data and output them in the console.

Q.js code:

const request = new XMLHttpRequest()
request.open('GET', '/friends.json')
request.onreadystatechange = ()=>{
  if(request.readyState===4 && request.status === 200){
    console.log(request.response)
  }
}

request.send()
Copy the code

Friends. json data:

[{"name":" Daniel wu "}, {"name":" Jay Chou "}]Copy the code

You can see that we successfully accessed the JSON data under the current source on the console.

  • Next we create a server using server with port number 9999. This server can request two files, index.html and frank.js. We send Ajax requests in frank.js to access friends.json from source 8888.

Frank. Js file:

function ajax(method, url) { return new Promise((resolve, reject) => { const request = new XMLHttpRequest(); request.open(method, url); request.onreadystatechange = () => { if (request.readyState === 4) { if (request.status === 200) { resolve(request.response); } else { reject(request); }}}; request.send(); }); } ajax (" get ", "http://127.0.0.1:8888/friends.json"). Then (response = > {the console. The log (" it's an ajax "); console.log(response); });Copy the code

Json file on port 8888. The console will give us an error:

We can see from the error message, we can see from thehttp://127.0.0.1:9999The Ajax request sent by this sourcehttp://127.0.0.1:8888/friends.json source data are blocked, the reason is CORSPolicy (Cross-domain resource sharing policy).

However, we need to note that our request was actually successful. We are listening for friends.json requests in the background of 8888, but the browser does not allow us to read the data under port 9999.

To summarize, browsers block access to other sources of data, but we can use data like JS, CSS, images and so on across domains. The reason is that the same origin policy of browsers only blocks access to data, not our data. We’re importing JS, CSS from other sources, We don’t really know what the internal data is, that is to say we can reference javascript from other pages with tags like Script but we don’t really know what the internal code is. If we want to use Ajax to request access to js from another source, we are constrained by the same origin policy.

Plan 1 CORS:

Since data from two different sources is not allowed to be accessed, what if I have two servers that want data from each other to be accessed? We can use the CORS method:

The CORS method is the simplest way to solve the cross-domain problem. Since we want to obtain the consent of other servers, we add a ‘note’ to the server where we need to access the resource, telling the server that if the source requests the data, we can allow it to access the data. This not only protects data security, but also ensures our cross-domain data access.

// Add a response header at the back end of our qq.com server when visiting friends.json. Responsetheader (" access-Control-allow-origin ", "http://127.0.0.1:9999");Copy the code

So when we look at our console on port 9999, we see that the error has disappeared and we have successfully requested the data using Ajax.

Scheme 2: JSONP

CORS is a very convenient cross-domain solution, but the only drawback is that IE6789 does not support it, so how can we cross domains without CORS support? Hence the second option, JSONP.

We said before that we can’t use Ajax to read data from other domain names, but we can use script tags to reference JS from other domain names. So we thought, we can use script tags to fetch JS files and entrap the requested data in js files. So how do we do that?

  • First, we call a function in the requested JS file. At the back end, when we find that the JS file is requested, we read the JS file and replace the parameters passed during the function call with the data we need to obtain (such as JSON data).

  • After that, we declare a function in the JS file that needs to request data. We use the script tag to request data and get a function call. The arguments passed by the function call are the data we need, and we can read the operation when we declare the function.

Call a function in the js file under the requested domain name, declare a function in the JS file that needs the requested data, and then use the script tag to access the JS file to indirectly get the data we need to request across the domain.

So here’s another question: How do we make sure that the function we declare is the same as the function we call? We declare a function on the window. How do we prevent the function name from repeating if we want to request multiple data? So:

  • We use random numbers as function names when we use script tags to request data. When we use script tags to request data, we add a callback parameter to the URL of the request, and read the random number represented by this parameter on our back end and replace it with the name of the called function.

This prevents function name conflicts and allows us to declare the same function name as the one called.

This completes the basic functionality of JSONP, but we can optimize it by encapsulating a script tag request as a method, encapsulating it with a Promise, and resolving the data from the declared function.

The code to send the request:

function jsonp(url) { return new Promise((resolve, reject) => { const random = "frankJSONPCallbackName" + Math.random(); // generate function name window[random] = data => {resolve(data); }; const script = document.createElement("script"); script.src = `${url}? callback=${random}`; // Pass script.onload = () => {script.remove(); // Finally remove the script tag we reference to make the HTML concise}; script.onerror = () => { reject(); }; document.body.appendChild(script); }); } the json (" http://127.0.0.1:8888/friends.js "). Then (data = > {the console. The log (data); });Copy the code

Listen for friends.js and change the parameters of the call function to data and the name of the replacement function we want:

response.statusCode = 200; response.setHeader("Content-Type", "text/javascript; charset=utf-8"); const string = `window['{{xxx}}']({{data}})` const data = fs.readFileSync("./public/friends.json").toString(); const string2 = string.replace("{{data}}", data).replace('{{xxx}}', query.callback); response.write(string2); response.end();Copy the code

To sum up:

What is the json?

  • A solution for situations where CORS is not allowed and can be adapted to Internet Explorer.
  • The process is that we use the script tag to request a JS file, which calls a function with the data we need. Use the data in the function declaration after you get it.
  • The function name is a random number that is passed to the back end via a GET request. The back end gets the parameter via refer and assigns the value to the function name.

Advantages of JSONP:

  • Compared to CORS, it is compatible with Internet Explorer.
  • It can cross domains

Disadvantages of JSONP:

  • It’s accessed using script tags, so you can’t get exact request status and response headers like Ajax.
  • Because it is a script tag, it cannot send a POST request.