logo头像

求知若渴,虚心若愚

浏览器 - 跨域解决方案 - 跨域资源共享(CORS)

跨域资源共享(CORS)

既然存在跨域问题,那么我们怎么解决这个问题呢?

  • W3C提出了一个标准,那就是CORS(跨域资源共享:Cross-origin resource sharing)
  • CORS需要浏览器和服务器同时支持
  • 如果设置了CORS,那么浏览器就会允许我们发送的ajax突破同源策略,向不同的服务器发送请求

CORS分类

  • 简单请求
  • 非简单请求

TIP
浏览器对两种请求的处理是不一样的!不一样啊不一样!

简单请求

  • 简单请求请求方法只有三种:

    • HEAD
    • GET
    • POST
  • 简单请求的请求头不超出以下字段

    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type只限于三个值:
      • application/x-www-form-urlencoded
      • multipart/form-data
      • text/plain

TIP
凡是不同时满足上面两个条件,就属于非简单请求

非简单请求(预检请求)

  • 除了简单请求以外的CORS请求
  • 非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUT或DELETE,或者Content-Type字段的类型是 application/json
  • 非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求,称为”预检”请求(preflight)

    • 浏览器先询问服务器,当前网页所在的域名是否在服务器的许可名单之中,以及可以使用哪些HTTP动词和头信息字段。
    • 只有得到肯定答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错
    • “预检”请求用的请求方法是OPTIONS,表示这个请求是用来询问的。
    • 头信息里面,关键字段是Origin,表示请求来自哪个源
  • 预检请求包含字段:

    • Origin:表示请求来自哪个源
    • Access-Control-Request-Method
      • 必须的
      • 用来列出浏览器的CORS请求会用到哪些HTTP方法
    • Access-Control-Request-Headers:
      • 该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段
    • Access-Control-Allow-Methods:
      • 必须
      • 它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。
      • 注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次”预检”请求。
    • Access-Control-Allow-Headers
      • 如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。
      • 它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在”预检”中请求的字段。
    • Access-Control-Max-Age
      • 可选
      • 用来指定本次预检请求的有效期,单位为秒。
1
2
3
4
5
6
7
8
9
10
11
12
HTTP/1.1 200 OK
Date: Fri, 9 Nov 2018 09:29:26 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: https://api.xuefeng666.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain

TIP
一旦服务器通过了”预检”请求,以后每次浏览器正常的CORS请求.
就都跟简单请求一样,会有一个Origin头信息字段。
服务器的回应,也都会有一个Access-Control-Allow-Origin头信息字段

CORS后台配置示例(NodeJs)

1
2
3
4
5
6
7
8
9
10
11
12
13
let app = express()
app.all('*',(req,res,next)=>{
// 消除中文乱码
res.set('Content-Type','application/json;charset=utf-8');

//设置跨域访问CORS
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "X-Requested-With");
res.header("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.header("X-Powered-By",' 3.2.1')
res.header("Content-Type", "application/json;charset=utf-8");
next();
})

TIP
如果要发送Cookie,Access-Control-Allow-Origin就不能设为通配符*
必须指定明确的,与请求网页一致的域名
并且Cookie依然遵循同源政策,只有用服务器域名设置的Cookie才会上传
其他域名的Cookie并不会上传,且原网页代码中的document.cookie也无法读取服务器域名下的Cookie。

支付宝打赏 微信打赏

赞赏是对我们的肯定!