CORS 预检响应如何实际缓存在浏览器中?

Posted

技术标签:

【中文标题】CORS 预检响应如何实际缓存在浏览器中?【英文标题】:How are CORS preflight responses actually cached in the browser? 【发布时间】:2016-07-04 08:35:26 【问题描述】:

一个技术性很强的问题,可能只有了解浏览器内部的人才能回答...

浏览器究竟如何缓存 CORS 预检响应(假设在对 OPTIONS 预检请求的响应中返回了 Access-Control-Max-Age 响应标头)?

基本上,在规范 (https://www.w3.org/TR/cors/#preflight-result-cache-0) 中,它说预检结果缓存中的每个条目都包含以下字段:

起源 网址 最大年龄 凭据 方法 标题

(方法和头是互斥的)

主缓存键由除 max-age 之外的所有字段组成。

因此,如果我收到对 OPTIONS 预检请求的响应,其中包含以下内容:

Access-Control-Allow-Origin: http://www.example.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: GET, POST, OPTION, HEAD
Access-Control-Allow-Headers: x-cool, x-special, x-sweet
Access-Control-Max-Age: 3600

那么我认为这会导致所有以下条目被添加到预检缓存中吗?

http://www.example.com  <url>  3600  true  GET
http://www.example.com  <url>  3600  true  POST
http://www.example.com  <url>  3600  true  OPTIONS
http://www.example.com  <url>  3600  true  HEAD
http://www.example.com  <url>  3600  true           x-cool
http://www.example.com  <url>  3600  true           x-special
http://www.example.com  <url>  3600  true           x-sweet

我的问题是:

    如果这是真的,这是否意味着在 OPTIONS 调用中返回所有可能允许的方法会更好(从性能 POV 来看),因此它们会立即添加到缓存中)。这与仅返回 Access-Control-Request-Method 请求标头中传递的实际方法形成对比。还是性能优势如此微不足道,甚至不值得问这个问题:) 是否有最大缓存大小? 有人知道为什么来源和网址是区分大小写的吗?

FWIW,我希望我可以指定 Access-Control-Allow-Headers: *(这意味着我的源服务器允许通过实际请求传递给它的所有标头)。同样,能够指定 Access-Control-Expose-Headers: * 会很好,所以我不需要为每一个都弄清楚是否需要将其公开给客户端 JS。由于无论如何它们都会在响应中传递,因此无法公开它们有点毫无意义 - 确保发出 CORS 请求的 JS 看不到它们,但这并不像它们对技术知识模糊的最终用户隐藏- 任何使用控制台或 Fiddler 或 Charles 的人都可以看到它们。

叹息。

更新:我与 Chrome 的一位开发人员交谈,他已确认无法查看 CORS 缓存(至少在 Chrome 中)。

更新 2: Access-Control-Allow-Headers: *Access-Control-Expose-Headers: * 均已添加到获取规范!耶!没有关于每种浏览器的哪些版本(如果有)支持它们的消息。

【问题讨论】:

【参考方案1】:

FWIW,我希望我可以指定 Access-Control-Allow-Headers:* (这意味着我的原始服务器允许将所有标头传递给它 实际请求)。同样,能够指定 访问控制公开标头:*

一个可能的解决方法是收集所有标题键并在 Access-Control-Expose-Headers 中返回。

【讨论】:

执行 Access-Control-Allow-Headers 很容易(因为我可以镜像回 Access-Control-Request-Headers 值,从而允许在请求中传递的所有标头)。但是,要返回 Access-Control-Expose-Headers,我需要知道所有可能与 GET 一起返回的响应标头。如果处理返回 OPTIONS 响应的 GET 的代码是相同的,那没关系,但这意味着我不能使用中间代理(例如 CDN 或负载均衡器)来返回它们,因为它们没有了解响应标头可能是什么

以上是关于CORS 预检响应如何实际缓存在浏览器中?的主要内容,如果未能解决你的问题,请参考以下文章

cors跨域之简单请求与预检请求(发送请求头带令牌token)

Rails 在 CORS 预检选项请求中以 404 响应

如何将 CORS 预检缓存应用于整个域

MVC6 Cors - 拦截预检

Ionic - $http 在移动设备中工作,但在浏览器中显示 CORS 和预检错误

预检 CORS 请求在 Chrome 60 中不起作用