【每日一题NO.82】CORS和预检请求

前端印记

共 2201字,需浏览 5分钟

 · 2021-11-14

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、请求方法:

必须为这几种的其中一个:GETPOSTHEAD

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 对象

复杂请求

非简单请求 即为复杂请求。复杂请求我们也可以称之为:在实际进行请求之前,需要发起预检请求的请求。

非简单请求是那种对服务器有特殊要求的请求,比如请求方法是PUTDELETE,或者Content-Type字段的类型是"application/json"。

跨域请求时,预检请求触发的条件

1、请求方法:

使用了下面任意 HTTP 方法的请求:PUTDELETECONNECTOPTIONSTRACEPATCH

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 方法发起一个预检请求到服务器,以获知服务器是否允许该实际请求
预检请求的使用,可以避免跨域请求对服务器的用户数据产生未预期的影响

参考资料

[1]

阮一峰-跨域资源共享 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
你也可以点击文末的 “阅读原文” 快速跳转


END
愿你历尽千帆,归来仍是少年。


浏览 75
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报