【每日一题NO.82】CORS和预检请求
CORS 跨域资源共享
目前几乎所有公司都是前后端分离的项目,前后端各自的代码部署在不同的服务器上,相互通信势必会引发跨域问题。
老生常谈的一个跨域解决方案就是 CORS (Cross-Origin Resource Sharing)。
使用该方案实现跨域需要前后端通力合作,需要服务器选择性的设置允许哪些跨域请求访问服务器的资源。
关于CORS的更多了解和设置可参考:跨域资源共享 CORS 详解[1]、CORS MDN[2]
后端设置支持CORS后,前端正常发送AJAX请求,如果CORS的跨域请求命中非简单请求的条件,浏览器会在正式通信前自动增加一次查询请求—— 预检请求(preflight)。
知道了预检请求和CORS的关联后,我们来详细看下什么是预检请求、什么情况下会触发预检请求。
OPTIONS 方法
先来看下 MDN 中一段关于 HTTP OPTIONS 方法的描述[3]:
HTTP 的OPTIONS
方法,用于获取目的资源所支持的通信选项。客户端可以对特定的 URL 使用OPTIONS
方法,也可以对整站(通过将 URL 设置为*
)使用该方法。
简单来说,就是可以用 OPTIONS
请求去嗅探某个请求在对应的服务器中都支持哪种请求方法。
预检请求
前面说了,在跨域的情况下,浏览器发起复杂请求前会主动发起 options 请求。(图中的第一个请求)
跨域共享标准规范要求,对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET
以外的 HTTP 请求,或者搭配某些 MIME
类型的 POST 请求),浏览器必须首先使用 options 方法发起一个预检请求,从而获知服务端是否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。
某些请求不会触发 CORS 预检请求,这样的请求一般称为简单请求,而触发预检请求则称为复杂请求。具体命中规则如下:
简单请求
满足以下条件的请求即为简单请求
1、请求方法:
必须为这几种的其中一个:GET
、POST
、HEAD
2、请求头
除了以下请求头字段之外,没有自定义的请求头
Accept
Accept-Language
Content-Language
Content-Type
DPR
Downlink
Save-Data
Viewport-Width
Width
Content-Type
得值 仅限于 下列三者之一:text/plain multipart/form-data application/x-www-form-urlencoded
3、关于XMLHttpRequestUpload
请求中的任意 XMLHttpRequestUpload
对象均没有注册任何事件监听器;XMLHttpRequestUpload
对象可以使用 "XMLHttpRequest.upload" 属性访问
4、没有ReadableStream对象
请求中没有使用 ReadableStream
对象
复杂请求
非简单请求 即为复杂请求。复杂请求我们也可以称之为:在实际进行请求之前,需要发起预检请求的请求。
非简单请求是那种对服务器有特殊要求的请求,比如请求方法是
PUT
或DELETE
,或者Content-Type
字段的类型是"application/json"。
跨域请求时,预检请求触发的条件
1、请求方法:
使用了下面任意 HTTP 方法的请求:PUT
、DELETE
、CONNECT
、OPTIONS
、TRACE
、PATCH
2、请求头
人为设置了以下集合之外的首部字段:
Accept
Accept-Language
Content-Language
Content-Type
DPR
Downlink
Save-Data
Viewport-Width
Width
Content-Type
的值不属于下列之一:application/x-www-form-urlencoded multipart/form-data text/plain
截图一个预检请求的请求头设置:
为什么要用预检请求
需预检的请求要求必须首先使用 OPTIONS
方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求。
预检请求的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响。
参考资料
阮一峰-跨域资源共享 CORS 详解: http://www.ruanyifeng.com/blog/2016/04/cors.html
[2]MDN-CORS跨域资源共享: https://developer.mozilla.org/zh-CN/docs/Glossary/CORS
[3]MDN-OPTIONS方法: https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods/OPTIONS
所有《每日一题》的 知识大纲索引脑图 整理在此:https://www.yuque.com/dfe_evernote/interview/everyday
你也可以点击文末的 “阅读原文” 快速跳转