CORS 简单请求与预检请求详解
CORS 简单请求与预检请求详解
Timmy在现代Web开发中,跨域资源共享(Cross-Origin Resource Sharing,CORS)是一个非常重要的安全机制,主要用于允许浏览器从不同源服务器访问资源。了解CORS的基本原理和其具体的请求类型,有助于开发者更好地控制前后端通信的安全性。本文将详细介绍CORS中的简单请求与预检请求。
什么是CORS?
CORS的定义
CORS是一个W3C标准,它允许浏览器安全地处理跨域请求。跨域请求指的是在不同域、协议或端口之间发起的HTTP请求。例如,假设前端应用运行在 http://example.com,而它需要向 http://api.example.com 获取数据,这就是一个跨域请求。
同源策略的限制
浏览器的同源策略(Same-Origin Policy,SOP)是Web安全模型的一部分,旨在阻止从一个源加载的文档与另一个源的资源进行不安全的交互。为了避免这些限制,CORS允许开发者定义哪些跨域请求是允许的。
CORS的工作原理
CORS的工作依赖于HTTP请求头和响应头的配合,通过设置特定的CORS相关头部,浏览器和服务器之间的跨域请求可以被安全地执行。
请求头
当浏览器发起跨域请求时,它会自动在请求中附加一些CORS相关的头部,最常见的是Origin头,用于指明请求的源。
响应头
服务器可以通过设置响应头来告知浏览器哪些跨域请求是被允许的。例如,Access-Control-Allow-Origin 用于明确允许哪些源可以访问资源。
CORS请求的分类
根据请求的复杂程度和安全性,CORS请求可以分为两类:
- 简单请求 (Simple Requests)
- 预检请求 (Preflight Requests)
接下来我们将详细讨论这两类请求的区别及其各自的特点。
简单请求(Simple Requests)
什么是简单请求?
简单请求是指那些不需要预检的跨域请求。这类请求必须满足一定的条件,包括使用特定的HTTP方法和头部。浏览器会直接发送简单请求而无需进行额外的安全检查。
简单请求的条件
根据CORS规范,只有符合以下所有条件的请求才被视为简单请求:
使用的HTTP方法 :仅限于
GET、POST、和HEAD。头部限制:请求头只能包含浏览器自动设置的以下三类头部:
AcceptAccept-LanguageContent-LanguageContent-Type(仅限值为application/x-www-form-urlencoded、multipart/form-data或text/plain)
不使用自定义头部 :如果请求头中包含其他任何自定义头部,则该请求将不再被视为简单请求。
浏览器的行为
对于简单请求,浏览器会直接发送请求,并且服务器通过在响应中设置CORS相关的头部来指明是否允许该请求。如果允许,浏览器将处理服务器返回的响应;否则,浏览器将阻止跨域请求并报错。
例子
假设我们有一个跨域请求,前端代码如下:
1 | fetch('https://api.example.com/data', { |
如果服务器允许跨域请求,它将在响应头中返回 Access-Control-Allow-Origin: *,从而允许所有来源的请求。
预检请求(Preflight Requests)
什么是预检请求?
当跨域请求不满足简单请求的条件时,浏览器会自动在正式请求之前发送一次OPTIONS请求,这个请求被称为预检请求。预检请求的目的是让浏览器确认服务器是否允许该类型的请求。
预检请求的触发条件
预检请求通常在以下情况下触发:
- 使用了简单请求之外的HTTP方法,例如
PUT、DELETE、或PATCH。 - 请求头中包含了自定义的头部字段。
Content-Type值为除application/x-www-form-urlencoded、multipart/form-data或text/plain之外的其他类型,例如application/json。
预检请求的流程
预检请求是由浏览器自动处理的,开发者无需手动发起。其流程如下:
- OPTIONS 请求 :浏览器首先发送一个
OPTIONS请求,询问服务器是否允许该跨域请求。这个请求中包含了以下头部:Origin: 指明请求的源。Access-Control-Request-Method: 说明即将发送的实际请求使用了哪种HTTP方法。Access-Control-Request-Headers: 说明实际请求中使用了哪些自定义头部。
- 服务器响应 :服务器接收到
OPTIONS请求后,通过返回相应的CORS头部来决定是否允许跨域请求。典型的响应头包括:Access-Control-Allow-Origin: 允许的请求源。Access-Control-Allow-Methods: 允许的HTTP方法。Access-Control-Allow-Headers: 允许的请求头。
- 实际请求 :如果服务器允许该跨域请求,浏览器才会发起实际的请求;否则,请求将被阻止。
例子
以下代码使用了 PUT 方法,并且请求头中包含了自定义的 Authorization 头部:
1 | fetch('https://api.example.com/update', { |
在这种情况下,浏览器会首先发送预检请求以确认服务器是否允许 PUT 请求和 Authorization 头部的使用。
CORS响应头详解
在CORS机制中,服务器通过设置以下头部来管理跨域请求的权限:
- Access-Control-Allow-Origin : 指定允许的请求源,可以是具体的域名或
*表示允许所有源。 - Access-Control-Allow-Methods : 指定允许的HTTP方法,例如
GET、POST、PUT等。 - Access-Control-Allow-Headers : 指定允许的自定义请求头,例如
Authorization、X-Requested-With。 - Access-Control-Allow-Credentials : 是否允许发送带有身份验证信息的请求,例如cookies。值为
true或false。
常见问题及解决方案
为什么跨域请求会失败?
最常见的原因是服务器未正确设置CORS响应头,或者浏览器阻止了不安全的跨域请求。开发者应确保服务器设置了正确的 Access-Control-Allow-Origin 等头部。
如何调试CORS问题?
可以使用浏览器的开发者工具来查看跨域请求的详细信息,检查请求和响应的头部,找出导致问题的具体原因。
总结
CORS是Web开发中的重要机制,能够确保跨域资源请求的安全性。理解简单请求与预检请求的区别,并正确配置服务器的CORS头部,可以帮助开发者避免跨域问题并提升用户体验。

