1. Same-origin policy

(1) What is the same-origin policy

Why do we talk about the same origin policy first, because what happens when you cross domains is you violate the same origin policy

Refer to MDN for an explanation of homology

The same origin policy is an important security policy that restricts how an Origin document or the scripts it loads can interact with resources from another source. It can help block malicious documents and reduce the number of vectors that can be attacked.

(2)homologousthedefine

Two urls are cognate if their protocol, port (en-us) (if specified), and host are the same. This scheme is also known as a “protocol/host/port tuple”, or simply “tuple”. (” tuple “refers to the whole of a group of items, in the general form of double/triple/quadruple/quintuple/etc.).

The following table gives the comparing with the URL http://store.company.com/dir/page.html source example:

URL The results of why
http://store.company.com/dir2/other.html homologous Only the path is different
http://store.company.com/dir/inner/another.html homologous Only the path is different
https://store.company.com/secure.html failure Agreement is different
http://store.company.com:81/dir/etc.html failure Different ports (http://The default port is 80)
http://news.company.com/dir/other.html failure The host different

2. How to solve cross-domain problems?

Cross-domain problems occur not because the server does not return the data in response, but because the browser restricts it

(1) the json

The json principle

Web pages can get JSON data dynamically generated from other sources by taking advantage of the <script> tag’s lack of cross-domain limitations. JSONP requests must be supported by the other party’s server.

Remark:

Comparison between JSONP and AJAX JSONP is the same as AJAX in that the client sends a request to the server to obtain data from the server. But AJAX is a same-origin policy,JSONP is a non-same-origin policy (cross-domain request)

The whole implementation process of JSONP

Advantages and disadvantages JSONP is simple and compatible, and can be used to solve the problem of cross-domain data access in mainstream browsers. The disadvantages are that supporting only get methods is limited and insecure and may be subject to XSS attacks.

  • Declare a callback function whose name (such as show) is passed to the server that requests data across domains and whose parameter is to fetch the target data (the data returned by the server).
  • Create a
  • Once the server receives the request, it needs to do something special: concatenate the name of the function passed in with the data it needs to give you into a string, for example: the name of the function passed in is show, and the data it prepares is show(‘ I like ping-pong ‘).
  • Finally, the server returns the data to the client through HTTP protocol, and the client calls the callback function (show) previously declared to operate on the returned data.

/ / encapsulates the json

jsonp.html
<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = s, initial - scale = 1.0">
    <title>Document</title>
</head>
<body>
    <script>
        function jsonp({ url, params, callback }) {
            return new Promise((resolve, reject) = > {
                let script = document.createElement('script');
                params = JSON.parse(JSON.stringify(params));
                let arrs = [];
                for (let key in params) {
                    arrs.push(`${key}=${params[key]}`);
                }
                arrs.push(`callback=${callback}`);
                script.src = `${url}?${arrs.join('&')}`;
                document.body.appendChild(script);
                window[callback] = function (data) {
                    resolve(data);
                    document.body.removeChild(script); }})}// front-end call
        jsonp({
            url: 'http://localhost:3000/hobby'.params: {
                wd: 'I Love play pingpang'
            },
            callback: 'show'
        }).then(data= > {
            console.log(data)
        })


    </script>
</body>
</html>
Copy the code

// The back-end code uses Express to create a back-end service

server.js
// Express is used here
var express = require('express');
var router = express.Router();
var app = express();
router.get('/hobby'.function(req,res,next) {
 // The data to respond back
  let data = {
    username : 'zhangsan'.password : 123456
  }

  let {wd , callback} = req.query;
  console.log(wd);
  console.log(callback);
  // Call the callback function and respond
  res.end(`${callback}(The ${JSON.stringify(data)}) `);
})
app.use(router);
app.listen(3000);
Copy the code

Start the service using node Server

(2) CORS (Cross-origin Resource Sharing)

CORS requires both browser and backend support. IE8 and IE9 need to use XDomainRequest to realize that the browser will automatically carry out CORS communication. The key to realize CORS communication is the back end. As long as the backend implements CORS, it implements cross-domain. To enable CORS, set access-Control-allow-Origin on the server. This attribute indicates which domain names can access resources. If a wildcard is set, all websites can access resources. Although setting up CORS has nothing to do with the front end, solving cross-domain problems in this way can result in two cases of simple and complex requests being sent.

A simple request

As long as the following two conditions are met, it is a simple request

Condition 1: Use one of the following methods:

  • GET
  • HEAD
  • POST

Condition 2: The value of the content-Type is limited to one of the following:

  • text/plain
  • multipart/form-data
  • Any XMLHttpRequestUpload object in the Application/X-www-form-urlencoded request does not register any event listeners;

Complex request

A request that does not meet the above conditions is a complex request. A CORS request of a complex request will add an HTTP query, called “precheck” request, before formal communication. This request is the option method, through which the server can know whether to allow cross-domain request. When a PUT request is sent to the background, it is a complex request. The background configuration is as follows:

// Which method is allowed to access me
res.setHeader('Access-Control-Allow-Methods'.'PUT')
// Precheck the survival time
res.setHeader('Access-Control-Max-Age'.6)
// OPTIONS request no processing
if (req.method === 'OPTIONS') {
  res.end() 
}
// Define what is returned in the background
app.put('/getData'.function(req, res) {
  console.log(req.headers)
  res.end('I like playing table tennis')})Copy the code

// Front-end code

cors.html
<! DOCTYPEhtml>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="Width = device - width, initial - scale = 1.0">
    <title>Document</title>
</head>
<body>
    <script>
        let xhr = new XMLHttpRequest();
        document.cookie = 'name=hw';
        xhr.withCredentials = true; // Set whether cookies are included in the front end
        xhr.open('PUT'.'http://localhost:4000/getData'.true);
        xhr.setRequestHeader('name'.'hw');
        xhr.onreadystatechange = function() {
            if(xhr.readyState === 4) {
                if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
                    console.log(JSON.parse(xhr.response));
                    console.log(xhr.getResponseHeader('name'))
                }
            }
        }
        xhr.send();
    </script>
</body>
</html>
Copy the code

// Create a port service for the front-end

let express = require('express');
let app = express();
app.use(express.static(__dirname))
app.listen(3000)
Copy the code

// Back-end code

cors.js
// Back-end code
let express = require('express')
let app = express()
let whitList = ['http://127.0.0.1:3000'] // Set the whitelist
app.use(function(req, res, next) {
  let origin = req.headers.origin
  if (whitList.includes(origin)) {
    // Set which source can access me
    res.setHeader('Access-Control-Allow-Origin', origin)
    // Which header is allowed to visit me
    res.setHeader('Access-Control-Allow-Headers'.'name')
    // Which method is allowed to access me
    res.setHeader('Access-Control-Allow-Methods'.'PUT')
    // Cookies are allowed
    res.setHeader('Access-Control-Allow-Credentials'.true)
    // Precheck the survival time
    res.setHeader('Access-Control-Max-Age'.6)
    // Allow return headers
    res.setHeader('Access-Control-Expose-Headers'.'name')
    if (req.method === 'OPTIONS') {
      res.end() // OPTIONS request no processing
    }
  }
  next()
})
app.put('/getData'.function(req, res) {
  let data = {
      username : 'zhangsan'.password : 123456
  }
  console.log(req.headers)
  res.setHeader('name'.'jw') // Return a response header that needs to be set in the background
  res.end(JSON.stringify(data))
})
app.get('/getData'.function(req, res) {
  console.log(req.headers)
  res.end('hhhhaha')
})
app.listen(4000)
Copy the code

// In the browser address bar, enter 127.0.0.1:3000/ cers.html

 

You can see that there are two getData requests

PUT request

The response Headers section

The Request Headers section

This implements a cross-domain request access from port 3000 to port 4000

The OPTIONS request

(3) Nginx solves cross-domain problems

In many ways to solve the cross domain, it is inevitable to need the support of the server, using Nginx can be pure front-end to solve the request cross domain problem

server
{
    listen 3002;
    server_name localhost;
    location /ok {
        proxy_pass http://localhost:3000;

        # specify methods that are allowed across domains, * for all
        add_header Access-Control-Allow-Methods *;

        # precheck the cache of the command, if not cached will send two requests each time
        add_header Access-Control-Max-Age 3600;
        # Cookie requests require this field and set to true
        add_header Access-Control-Allow-Credentials true;

        # indicates that this domain is allowed to make cross-domain calls (the domain name and port from which the client sends the request)
        # $http_origin does not use * because requests with cookies do not support *
        add_header Access-Control-Allow-Origin $http_origin;

        # represents the dynamic retrieval of fields in the request header
        add_header Access-Control-Allow-Headers 
        $http_access_control_request_headers;

        The request will not be sent until the precheck command passes
        Check whether the type of request is a precheck command
        if ($request_method = OPTIONS){
            return200; }}}Copy the code