跳转到主要内容

category

浏览器的同源策略阻止从不同的源读取资源。这种机制阻止恶意网站读取其他网站的数据,但也阻止合法使用。

现代web应用程序通常希望从不同的来源获取资源,例如,从不同的域检索JSON数据,或将另一个网站的图像加载到<canvas>元素中。这些可以是公共资源,任何人都可以阅读,但同源政策阻止了它们的使用。开发人员历来使用诸如JSONP之类的变通方法。

跨来源资源共享(CORS)以标准化的方式解决了这个问题。启用CORS可以让服务器告诉浏览器它可以使用一个额外的原点。

资源请求是如何在网络上工作的?


请求和响应
图示客户端请求和服务器响应。
浏览器和服务器可以使用超文本传输协议(HTTP)在网络上交换数据。HTTP定义了请求者和响应者之间的通信规则,包括获取资源所需的信息。

HTTP头协商客户端和服务器之间的消息交换,并用于确定访问权限。浏览器的请求和服务器的响应消息都分为头和正文。

头信息


有关消息的信息,例如消息的类型或消息的编码。报头可以包括表示为键值对的各种信息。请求标头和响应标头包含不同的信息。

示例请求标头

Accept: text/html
Cookie: Version=1


这个标题相当于说“我想接收HTML作为响应。这是我的一个cookie。”

样本响应标头

Content-Encoding: gzip
Cache-Control: no-store


这个头相当于说“这个响应中的数据是用gzip编码的。不要缓存这个。”

注意:标题不能包含注释。


身体


信息本身。这可以是纯文本、图像二进制、JSON、HTML或许多其他格式。

CORS是如何工作的?


同源策略告诉浏览器阻止交叉源请求。当您需要来自不同来源的公共资源时,资源提供服务器告诉浏览器发送请求的来源可以访问其资源。浏览器会记住这一点,并允许该资源的跨来源资源共享。

步骤1:客户端(浏览器)请求


当浏览器发出跨原点请求时,浏览器会添加一个具有当前Origin 方案、主机和端口)的Origin 标头。

步骤2:服务器响应


当服务器看到此标头并希望允许访问时,它会将Access-Control-Allow-Origin标头添加到指定请求来源的响应中(或*以允许任何来源)

步骤3:浏览器接收响应


当浏览器看到此响应带有适当的Access-Control-Allow-Origin标头时,它会与客户端站点共享响应数据。

与CORS共享凭据


出于隐私原因,CORS通常用于匿名请求(anonymous requests),其中请求者没有被识别。如果你想在使用CORS时发送cookie,它可以识别发送者,你需要在请求和响应中添加额外的头。

请求


将凭据:“include”添加到提取选项中,如下例所示。这包括带有以下请求的cookie:

fetch('https://example.com', {
  mode: 'cors',
  credentials: 'include'
})


应答


Access-Control-Allow-Origin必须设置为特定来源(不使用通配符*),并且访问控制允许凭据必须设置为true。

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true


复杂HTTP调用的预处理请求


当web应用程序发出复杂的HTTP请求时,浏览器会在请求链的开头添加一个飞行前请求。

CORS规范对复杂请求的定义如下:

  • 使用GET、POST或HEAD以外的方法的请求。
  • 包含Accept、Accept Language或Content Language以外的标头的请求。
  • 具有内容类型标头而非application/x-www-form-urlencoded、multipart/form-data或text/plain的请求。


浏览器会自动创建任何必要的飞行前请求,并在实际请求消息之前发送。飞行前请求是OPTIONS请求,如以下示例所示:

OPTIONS /data HTTP/1.1
Origin: https://example.com
Access-Control-Request-Method: DELETE


在服务器端,接收请求的应用程序用有关应用程序从该来源接受的方法的信息来响应飞行前请求:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Methods: GET, DELETE, HEAD, OPTIONS


服务器响应还可以包括Access Control Max Age标头,以指定缓存飞行前结果的持续时间(以秒为单位)。这允许客户端发送多个复杂的请求,而无需重复飞行前请求。

文章链接