跨域资源共享Cross-Origin Resource Sharing (CORS)
浏览器的同源策略阻止读取来自不同来源的资源。 这种机制阻止恶意站点读取另一个站点的数据,但它也阻止合法使用。
在现代 Web 应用程序中,应用程序通常希望从不同来源获取资源。例如,您想要从不同的域中检索 JSON 数据或将来自另一个站点的图像加载到 <canvas>
元素中
资源的请求是怎么在web中共工作的?
浏览器和服务器可以使用超文本传输协议 (HTTP) 通过网络交换数据。 HTTP 定义了请求者和响应者之间的通信规则,包括获取资源所需的信息。
HTTP 头用于协商客户端和服务器之间的消息交换类型,并用于确定访问权限。浏览器的请求和服务器的响应消息都分为header和body两部分
header
有关消息的信息,例如消息类型或消息编码。header可以包括表示为键值对的各种信息。请求头和响应头包含不同的信息。
简单的请求头
Accept: text/html
Cookie: Version=1
以上相当于说“我想接收 HTML 作为响应。这是我拥有的一个 cookie”。
简单的响应头
Content-Encoding: gzip
Cache-Control: no-store
上面相当于说“数据是用gzip编码的。请不要缓存它。”
body
消息本身。这可以是纯文本、二进制图像、JSON、HTML 等。
CORS是怎么工作的?
请记住,同源策略告诉浏览器阻止跨源请求。 当你想从不同的源获取公共资源时,资源提供服务器需要告诉浏览器“请求来自的这个源可以访问我的资源”。 浏览器记住这一点并允许跨源资源共享
步骤一:客户端(浏览器)请求
当浏览器发出跨域请求时,浏览器会添加一个带有当前源(方案、主机和端口)的 Origin
标头。
步骤 2:服务器响应
在服务器端,当服务器看到这个头,并想要允许访问时,它需要在指定请求来源的响应中添加一个 Access-Control-Allow-Origin 头(或 * 允许任何 origin.)
步骤 3:浏览器接收响应
当浏览器看到此响应带有适当的 Access-Control-Allow-Origin 标头时,浏览器允许与客户端站点共享响应数据。
复杂 HTTP 调用的预检请求
如果 Web 应用程序需要复杂的 HTTP 请求,浏览器会在请求链的前面添加一个预检请求。
CORS 规范将复杂请求定义为
- A request that uses methods other than GET, POST, or HEAD
- A request that includes headers other than Accept, Accept-Language or Content-Language
- A request that has a Content-Type header other than application/x-www-form-urlencoded, multipart/form-data, or 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 标头来指定缓存预检结果的持续时间(以秒为单位),这样客户端就不需要在每次发送复杂请求时都发出预检请求