CORS

本文根据JavaScript标准参考教程 整理笔记. 代码也来源于此

CORSW3C标准, 全名叫跨域资源共享Cross-origin resource sharing
它允许浏览器向垮源服务器发出XMLHttpRequest请求.
CORS需要浏览器和服务器都支持

浏览器将CORS分为两类, 简单请求和非简单请求.
只要满足下面的两类就属于简单请求:

  1. 请求方法是HEAD, GET, POST三种方法之一
  2. HTTP的头信息不超过下面的字段
    • Accept
    • Accept-Language
    • Content-Language
    • Last-Event-ID
    • Content-Type:只限于三个值application/x-www-form-urlencodedmultipart/form-datatext/plain

不属于简单请求的就是非简单请求

简单请求

  • 浏览器对于简单请求, 在请求报文中增加origin字段, 然后直接发送给服务器. origin字段表示请求来自哪个源(协议+域名+端口)
  • 服务器接收到请求后, 会发送一个HTTP响应, 若响应中包含Access-Control-Allow-Origin字段则表示发送请求的源在允许的范围内
    • 若响应不包含Access-Control-Allow-Origin信息, 则表示出错了. 我们可以使用XMLHttpRequest.onerror的回调函数处理. 不能使用http状态码, 因为无论服务器是否允许源通信, 服务器都会发送响应给浏览器, 说明状态码为200
    • 服务器返回的响应除了Access-Control-Allow-Origin属性, 还会有其他属性如:
      • Access-Control-Allow-Origin :该字段是必须的。它的值要么是请求时origin字段的值,要么是一个*,表示接受任意域名的请求
      • Access-Control-Allow-Credentials: 可选字段, 为true表示允许发送Cookie. 同时, 发送时, 必须设置XMLHttpRequest.withCredentials为true才有效. 请求若服务器不允许浏览器发送, 删除该字段即可.
      • Access-Control-Expose-Headers: 可选字段, 指定发送请求时的其他头字段

非简单请求

非简单请求会在正式通信之前发送一次HTTP的查询请求, 称为预检请求
服务器收到预检请求后检查请求中的字段再做出响应
若浏览器收到的响应确定允许垮源通信, 则浏览器就会像简单请求一样做出正常的请求.

预检请求

浏览器发送请求询问当前域名是否支持跨域, 能使用哪些HTTP动词及头字段信息等.
预检请求的头信息:

OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...
  1. OPTIONS表示这个请求是询问的, origin表示预检请求来自哪个源
  2. Access-Control-Request-Method: 该字段必须, 列出浏览器的CORS请求会用到哪些HTTP方法
  3. Access-Control-Request-Headers: 该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是X-Custom-Header。这个字段通常在XMLHttpRequest.setRequestHeader()方法中已经设置好了

预检请求的回应

服务器收到预检请求后, 会检查预检请求的字段是否符合服务器的垮源规定.
若允许垮源, 则做出回应, 服务器会发送一个包含Access-Control-Allow-Origin字段的响应报文给浏览器, 例如:

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.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
  1. Access-Control-Allow-Methods:该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次“预检”请求
  2. Access-Control-Allow-Headers: 如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在“预检”中请求的字段。
  3. Access-Control-Max-Age: 该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求

浏览器的正常请求和回应

服务器通过了预检请求后, 浏览器发送的请求中就有origin字段, 服务器响应也会有Access-Control-Allow-Origin字段, 这些是自动添加的. 就和简单请求一样了.

与JSONP比较

JSONP只支持GET请求, 以为动态创建的script标签只支持GET请求. 支持老式浏览器
DORS支持所有的HTTP请求.

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值