预检请求
什么是预检请求?
对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是
GET
以外的 HTTP 请求,或者搭配某些 MIME 类型的POST
请求),浏览器必须首先使用OPTIONS
方法发起一个预检请求(preflight request),从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。 CORS请求失败会产生错误,但是为了安全,在JavaScript代码层面是无法获知到底具体是哪里出了问题。你只能查看浏览器的控制台以得知具体是哪里出现了错误。
什么情况下会有预检请求
请求会对服务器有影响的会先法预检请求
当请求满足下述任一条件时,即应首先发送预检请求:
- 使用了下面任一 HTTP 方法:
- 人为设置了对 CORS 安全的首部字段集合之外的其他首部字段。该集合为:
Accept
Accept-Language
Content-Language
Content-Type
(需要注意额外的限制)[DPR](http://httpwg.org/http-extensions/client-hints.html#dpr)
[Downlink](http://httpwg.org/http-extensions/client-hints.html#downlink)
[Save-Data](http://httpwg.org/http-extensions/client-hints.html#save-data)
[Viewport-Width](http://httpwg.org/http-extensions/client-hints.html#viewport-width)
[Width](http://httpwg.org/http-extensions/client-hints.html#width)
Content-Type
的值不属于下列之一:application/x-www-form-urlencoded
multipart/form-data
text/plain
- 请求中的
XMLHttpRequestUpload
对象注册了任意多个事件监听器。 - 请求中使用了
ReadableStream
对象。
简单请求
什么是简单请求?
某些请求不会触发 CORS 预检请求。本文称这样的请求为“简单请求”,请注意,该术语并不属于 Fetch (其中定义了 CORS)规范。若请求满足所有下述条件,则该请求可视为“简单请求”:
什么请求是简单请求
按照预检请求的理解,简单请求就是对服务器无副作用的请求。
- 使用下列方法之一:
- Fetch 规范定义了对 CORS 安全的首部字段集合,不得人为设置该集合之外的其他首部字段。该集合为:
Accept
Accept-Language
Content-Language
Content-Type
(需要注意额外的限制)[DPR](http://httpwg.org/http-extensions/client-hints.html#dpr)
[Downlink](http://httpwg.org/http-extensions/client-hints.html#downlink)
[Save-Data](http://httpwg.org/http-extensions/client-hints.html#save-data)
[Viewport-Width](http://httpwg.org/http-extensions/client-hints.html#viewport-width)
[Width](http://httpwg.org/http-extensions/client-hints.html#width)
Content-Type
的值仅限于下列三者之一:text/plain
multipart/form-data
application/x-www-form-urlencoded
- 请求中的任意
XMLHttpRequestUpload
对象均没有注册任何事件监听器;XMLHttpRequestUpload
对象可以使用XMLHttpRequest.upload
属性访问。 - 请求中没有使用
ReadableStream
对象。
POST为什么分简单和不简单
**
搭配某些 MIME 类型的
POST
请求,需要发送预检请求,怎么理解? 为什么POST请求划分到简单请求里?
为什么content-type为下面三种的却被视为简单请求,工作中碰到的post请求很多都会采用下面的格式,且会修改数据库内容,其不会存在安全风险吗?
- text/plain
- multipart/form-data
- application/x-www-form-urlencoded
如果我们现在重新设计整个HTTP协议,我们可以要求浏览器在发送任何数据到另外一个域的服务器之前,都必须先发送preflight request。但是大部分现存网站并未针对preflight request做出实现,所以这意味着现有的互联网中,如果一个域的表单向另一个域提交的时候会跨域失败,直到目标网站更新处理perflight request为止。
所以在我们制定这一新的标准的时候,应当考虑到目前互联网已经存在这样的请求,他们虽然看起来可能不安全,但为了向下兼容,我们不能强制对这些请求做preflight request。既然不能强制做preflight request验证,那发这个东西就没有什么意义了。
可能是为了向下兼容表单提交吧,表单提交出现比同源策略要早。
参考mdn
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS#Preflighted_requests
知乎
https://www.zhihu.com/question/268998684