AJAX cross-domain solutions

This is the 22nd day of my participation in the August Wen Challenge.More challenges in August

1. Separation mode of front and rear ends

  • Static Resources (HTML) –server-aProvide front-end static resources.
  • Back-end data (commodity information…) –server-bOffer based onHTTPAPI.

2. Same-origin policy

The same origin policy protocol is triggered when we use XHR to fetch data from one source to another.

The source

Domain: protocol + host (IP address or domain name) + port, for example, http://localhost:8888.

The same-origin policy

A security mechanism used by browsers to prevent the use of scripts to obtain non-homogeneous data.

3. Cross-domain solution: CORS

This mechanism is built on a core content: HTTP headers. This mechanism defines a set of HTTP headers through which access to resources is controlled. These HTTP headers are basically access-Control -? Different HTTP headers have different functions.

Reference: developer.mozilla.org/zh-CN/docs/…

Common Resource request

Access-Control-Allow-Origin

Controls the origin that is currently allowed to access the resource.

Non-ordinary resource request

Simple request & Non-simple request

If the request meets certain rules, it is a simple request

Reference: developer.mozilla.org/zh-CN/docs/…

Preview the request

If the current request meets the non-simple request, a request (browser) with method options is sent first, which is called precheck. The back end needs to process the precheck request and return the corresponding header information according to the service to inform the client whether to allow the non-simple request. We need to return a series of headers in the precheck request to control whether the previously sent non-simple request continues

Reference: developer.mozilla.org/zh-CN/docs/…

4. Cross-domain solution: back-end proxy

In addition to js being able to send HTTP requests through some API, many other languages can do this, so can Node.js. Node.js is not restricted by the same origin policy, so we can use static resources (i.e. the resource server from which THE JS request is sent) to send the request and then forward it. We call it: agent.

Provide API service server: ServerA

Source: http://localhost:8888

const Koa = require('koa');
const KoaRouter = require('koa-router');

const app = new Koa();
const router = new KoaRouter();

router.get('/data'.async (ctx, next) => {
    ctx.body = [1.2.3.4.5];
})

app.use(router.routes());

app.listen(8888);
Copy the code

The server that sends THE JS request: ServerB

const Koa = require('koa');
const KoaStaticCache = require('koa-static-cache');
const KoaRouter = require('koa-router');
const http = require('http');

const app = new Koa();

app.use(KoaStaticCache({
    prefix: ' '.dir: './public'.gzip: true.dynamic: true
}));

// Cross-domain issues: browsers have same-origin policy restrictions, but not necessarily others. Many languages have web-based programming that can listen for requests,
    // Requests can also be sent, and there is generally no same-origin policy by default
// We can provide HTTP modules based on Node to send requests
// This URL is the forward interface to send ajax requests to our current js server
router.get('/data'.async (ctx, next) => {

    // Use to send an HTTP request to the real server interface
    // Back-end proxy
    // [server1.ajax => server1] => server2, server1 is the proxy
    return new Promise((resolve, reject) = > {
        let req = http.request({
            // method: 'get',
            hostname: 'localhost'.port: 8888.path: '/data'
        }, (res) = > {
            let data = ' ';
            res.on('data'.(chunk) = > {
                data += chunk.toString();
            });
            res.on('end'.() = > {
                console.log('Data:', data);
                ctx.body = data;
                resolve();
            });
        });

        req.write(' '); req.end(); })}); app.use(router.routes()); app.listen(9999);
Copy the code

JS request in ServerB

let xhr = new XMLHttpRequest();
// Data must add the address of the current js server
xhr.open('/get'.'/data');
xhr.onload = function() {
  console.log(this.responseText);
}
xhr.send();
Copy the code

5. Cross-domain certificate information processing

5-1, based onCookieCORSTo deal with

Cookies are also restricted by the same origin policy. If a request is not from the same origin, cookies are prohibited by default.

Request with credentials

  • The client sets the following parameters in the request:withCredentials: true
  • The server should be set in CORS:ctx.set('Access-Control-Allow-Credentials', 'true');

5-2, based onTokenThe authentication mechanism of the

Cookie-based authentication has some problems:

  • Whether or not the current request needs to be deliveredCookie, the browser will actively send (waste).
  • Easy to beCSRFAttack.

The 5-2-1,JWTintroduce

Json Web Token (JWT) is an open jSON-based standard implemented to transfer claims between network application environments.

Reference: JWT. IO/introductio…

Composition structure:

JWT is made up of three pieces of text linked by a

let header = `{ "alg": "HS256", "typ": "JWT" }`;
let payload = `{ "sub": "1234567890", "name": "John Doe", "iat": 1516239022 }`;
let key = '* * *';

let sign = HMACSHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),
 key
);

let token = `${base64UrlEncode(header)}.${base64UrlEncode(payload)}.${sign}`;
Copy the code

Token content generated:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.E1H9eRej 3pbltuEr9IL12jJjb-612z_q1eEfvNKK0t8Copy the code

header

ALGORITHM & TOKEN TYPE, which TYPE and the ALGORITHM used.

payload

Stored data

sign

The signature

In the 5-2-2 s, the use ofJWT

We can use JsonWebToken to implement token generation and validation

npm install jsonwebtoken
Copy the code
/ / the back end.const jwt = require('jsonwebtoken');

const signKey = '* * *'; . router.post('/login'.async (ctx, next) => {
  
  let user = {id: 1.username: 'zMouse'};
  
  const token = jwt.sign(user, signKey);
  
  // Send through header Authorization
  ctx.set('Authorization', token);
  
  ctx.body = 'Login successful';
})

router.get('/user/profile'.async (ctx, next) => {
  let user = null;
  try {
    let 
    let token = ctx.get('Authorization');
    user = jwt.sign(token, signKey);
    if(! user) { ctx.throw(401.'No access');
    }
    ctx.body = 'Accessible'; }})...Copy the code

After the client successfully requests login, it obtains the token, which can be saved in the client using methods such as localStorage.

function login() {
  let xhr = new XMLHttpRequest();
  xhr.open('post'.'/login');
  xhr.onload = function() {
    if ( xhr.status >= 200 && xhr.status < 300 ) {
      let token = xhr.getResponseHeader('Authorization');
      localStorage.setItem('token', token);
    }
  }
  xhr.send(JSON.stringify({username:'Kobe Bryant'.password: '123456'}));
}

function getUserProfile() {
  let xhr = new XMLHttpRequest();
  xhr.open('get'.'/user/profile');
  xhr.onload = function() {
    console.log(xhr.responseText);
  }
  let token = localStorage.getItem('token');
  xhr.setRequestHeader('Authorization'.`Bearer ${token}`);
  xhr.send();
}
Copy the code

6. Fetch request

The Fetch API provides an interface to Fetch resources (including cross-domain requests). Anyone who has ever worked with XMLHttpRequest should be able to get started, and the new API offers a much more powerful and flexible set of features. Some definitions of common objects are also provided:

  • Reuqest
    • An object that operates on a resource request.
  • Response
    • The object that operates on the response resource.
  • Headers
    • An object that retrieves, sets, adds, deletes, and so on header information.
const myHeaders = new Headers();
myHeaders.append('Content-Type'.'application/json');

const myRequest = new Request('/user', {
  method: 'post'.headers: myHeaders,
  body: JSON.stringify({username: 'Kobe Bryant'.password: '123456'})});// res => Response object
let res = await fetch(myRequest);
let data = await res.json();
// let data = await res.text();
Copy the code

XMLHttpRequest Vs Fetch

XMLHttpRequest

  • Support for request and response progress events
  • Support request cancellation:abort

Fetch

  • More standard, standardAPISupport.
    • HeaderRequestResponsePromiseCORS