九种跨域解决方案使用示例(2)-CORS

CORS全称

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源(协议 + 域名 + 端口)服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

CORS使用限制

CORS 需要浏览器和后端同时支持。
IE 8 和 9 需要通过 XDomainRequest 来实现。

CORS实现方式

服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。

CORS基本流程

浏览器将CORS请求分为两类:简单请求(simple request)和非简单请求(not-so-simple request)
简单请求,只需要在头信息之中增加一个Origin字段。
非简单请求,会在正式通信之前,增加一次HTTP查询请求,称为"预检"请求(preflight)。浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错。

只要同时满足以下两大条件,就属于简单请求。

  1. 请求方法是以下三种方法之一:
  • GET
  • POST
  • HEAD
  1. 请求header里面:
  • 无自定义头
  • Content-Type只限于以下三个值
    • application/x-www-form-urlencoded
    • multipart/form-data
    • text/plain

CORS示例

前端

let xhr = new XMLHttpRequest();
    xhr.withCredentials = true;
    xhr.open('PUT', 'http://localhost:8090/testCors', true);
    // xhr.open('get', 'http://localhost:8090/testCors', true);

    xhr.setRequestHeader('name', 'Lee');

    xhr.onreadystatechange = () => {
      if (xhr.readyState === 4) {
        if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
          console.log(xhr.response, xhr.getResponseHeader('name')); // put/get, zhang
        }
      }
    };

    xhr.send();

后端(以nodejs为例)

const express = require('express');

const app = express();
const whiteList = ['http://localhost:1820'];

app.use((req, res, next) => {
  const origin = req.headers.origin;

  if (whiteList.includes(origin)) {
    // 设置哪个源可以访问我
    res.setHeader('Access-Control-Allow-Origin', origin);
    // 允许携带哪个头访问我
    res.setHeader('Access-Control-Allow-Headers', 'name');
    // 允许哪个方法访问我
    res.setHeader('Access-Control-Allow-Methods', 'PUT');
    // 允许携带cookie
    res.setHeader('Access-Control-Allow-Credentials', true);
    // 预检的存活时间
    res.setHeader('Access-Control-Max-Age', 6);
    // 允许返回的头
    res.setHeader('Access-Control-Expose-Headers', 'name');
  }
  next();
});

app.put('/testCors', (req, res) => {
  console.log(req.headers);
  // 返回一个后台的响应头
  res.setHeader('name', 'zhang');
  res.end('put');
});
app.get('/testCors', (req, res) => {
  console.log(req.headers);
  res.end('get');
});

app.listen(8090);

你可能感兴趣的:(九种跨域解决方案使用示例(2)-CORS)