HTTP学习——跨域资源共享(CORS)

介绍

跨域资源共享 (CORS)(或通俗地译为跨域资源共享)是一种基于 HTTP 头的机制,该机制通过允许服务器标示除了它自己以外的其它 origin(域,协议和端口),使得浏览器允许这些 origin 访问加载自己的资源。如果浏览器符合服务器的要求,那么它将可以访问此服务器host内的内容

跨域HTTP 请求的一个例子:运行在 https://a.com 的 JavaScript 代码使用XMLHttpRequest来发起一个到 https://b.com/data.json 的请求。

但是浏览器会限制JS跨域HTTP的请求,跨域资源共享(CORS)机制允许 Web 应用服务器进行跨源访问控制,从而使跨源数据传输得以安全进行

通常由axios(AJAX)即内部的XMLHttpRequestFetch APIs发起的跨域HTTP请求需要用到CORS,还有一些Web字体。图像等

变化

CORS新增了一组 HTTP 首部字段,允许服务器声明哪些源站通过浏览器有权限访问哪些资源。
另外,有时候,非GET请求需要首先使用OPTIONS方法发起一个预检请求,从而知道服务器是否允许我们跨域请求
在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 CookiesHTTP 认证 相关数据)。

简单请求

不会触发CORS预检请求的请求称为简单请求,要求满足下列所有条件:
①使用GET,POST,HEAD
②处于下列首部字段内

Accept
Accept-Language
Content-Language
Content-Type(需要注意额外的限制)

③Content-Type 的值仅限于下列三者之一:

text/plain
multipart/form-data
application/x-www-form-urlencoded

④请求中的任意 XMLHttpRequest 对象均没有注册任何事件监听器;XMLHttpRequest 对象可以使用 XMLHttpRequest.upload 属性访问以及请求中没有使用 ReadableStream 对象

CORS实例

比如说,假如站点 https://foo.example 的网页应用想要访问 https://bar.other 的资源。foo.example 的网页中可能包含类似于下面的 JavaScript 代码:

const xhr = new XMLHttpRequest();
const url = 'https://bar.other/resources/public-data/';

xhr.open('GET', url);
xhr.onreadystatechange = someHandler;
xhr.send();

那么客户端和服务器之间使用 CORS 首部字段来处理权限:
请求头:

GET /resources/public-data/ HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: https://foo.example

请求首部字段 Origin 表明该请求来源于 http://foo.example
响应头:

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 00:23:53 GMT
Server: Apache/2
Access-Control-Allow-Origin: *
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Transfer-Encoding: chunked
Content-Type: application/xml

[XML Data]

Access-Control-Allow-Origin: *说明该网站内的该资源可以被任意网址访问
Access-Control-Allow-Origin: https://foo.example说明该网站内的该资源只能允许来自https://foo.example访问

预检请求实例

请求头
OPTIONS /doc HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
Origin: https://foo.example
Access-Control-Request-Method: POST
上面表示实际请求是POST
Access-Control-Request-Headers: X-PINGOTHER, Content-Type
上面表示将会携带自定义的2个头

响应头
HTTP/1.1 204 No Content
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2
Access-Control-Allow-Origin: https://foo.example
上面表示允许访问的origin
Access-Control-Allow-Methods: POST, GET, OPTIONS
上面表示允许的几个发送信息方式
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
上面表示允许的几个携带自定义的头
Access-Control-Max-Age: 86400
上面指定了 preflight 请求的结果能够被缓存几秒(s)
Vary: Accept-Encoding, Origin
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive

预检请求完成之后,发送实际请求:

POST /doc HTTP/1.1
Host: bar.other
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:71.0) Gecko/20100101 Firefox/71.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Connection: keep-alive
X-PINGOTHER: pingpong
Content-Type: text/xml; charset=UTF-8
Referer: https://foo.example/examples/preflightInvocation.html
Content-Length: 55
Origin: https://foo.example
Pragma: no-cache
Cache-Control: no-cache

<person><name>Arun</name></person>

HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:40 GMT
Server: Apache/2
Access-Control-Allow-Origin: https://foo.example
Vary: Accept-Encoding, Origin
Content-Encoding: gzip
Content-Length: 235
Keep-Alive: timeout=2, max=99
Connection: Keep-Alive
Content-Type: text/plain

[Some XML payload]

其中,xhr对象的withCredentials方法=true时会向服务器发送cookie
但是,如果服务器端的响应中未携带 Access-Control-Allow-Credentials: true,浏览器将不会把响应内容返回给请求的发送者。

感谢,参考来自MDN

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值