CORS访问控制的Access-Control-Max-Age被忽略了。

37

我正在将WebApp和其API托管在不同的域上,并使用CORS以便绕过同源策略。到目前为止,一切都很好。这个可以工作。

为了每个会话仅发送一次CORS预检请求,我将Access-Control-Max-Age设置为20天,但这并没有起作用(在Chrome中测试):https://db.tt/vfIW3fD2

我需要做出什么改变?

3个回答

119
如果你使用 Chrome 开发者工具,请确保你的 "Disable cache (while DevTools is open)" 选项未勾选。我之前遇到了 "Access-Control-Max-Age" 没有被识别的问题,后来才发现是因为我勾选了这个选项。

13
你绝对帮我解决了一个大问题!!之前忘记检查那个了:D - Dunos
2
这很明显,但是... 我从来没有想过!谢谢! - Kevin Gaudin
1
刚刚意识到开发工具中有这样的东西,而且它起作用了,谢谢。 - AamirR

25

Chrome/Blink实施了一个最大预检时间为10分钟(600秒)的限制。以下是定义此限制的源代码位置:

https://chromium.googlesource.com/chromium/blink/+/master/Source/core/loader/CrossOriginPreflightResultCache.cpp#40

超过10分钟的任何预检时间都将被忽略,而将使用10分钟。

不同的浏览器可能有不同的“最大年龄”策略。Safari/WebKit缓存长达5分钟,而Firefox缓存长达24小时。Chrome源代码表明,该最大值存在是为了“在切换到安全网络后最小化使用受污染的缓存的风险”。

如果代码无法解析max-age标头(或服务器未指定max-age标头),则浏览器默认为5秒。


1
你好,感谢解释。这仍然没有解释为什么预检请求在5秒后再次执行。有什么想法吗? - Roland Schütz
我更新了答案,并添加了一个关于何时选择5秒超时的部分。但在你的情况下,超时应该是5分钟而不是5秒,因为你的max-age头看起来是有效的。它可能是+Ray Nicholus上面提到的(头或来源不匹配)的唯一其他事项。你能在test-cors.org上重现这个问题吗? - monsur
我无法在test-cors.org上重现问题,因为问题发生在第二个请求中。这是我的请求和响应,应该(但没有)导致缓存的OPTIONS请求。https://gist.github.com/rolandschuetz/cd278a9489b5065a256d - Roland Schütz
2
经过2年,谷歌浏览器仍然忽略缓存 :(... 在54.0.2840.50 beta (64-bit)上测试过。 - LiberQuack

10

我不会过分依赖预检测缓存。

从规范来看:

用户代理在max-age字段指定的时间之前可能会清除缓存条目。

此外,请记住以下内容(来自CORS规范):

当预检结果缓存中存在缓存条目并满足以下条件时,就会出现缓存匹配:

源操作值对大小写敏感匹配源来源。

url字段值对大小写敏感匹配请求URL。

凭据字段值为true且省略凭据标志未设置,或者它为false并且省略凭据标志已设置。

您的屏幕截图无法确定上述任何一项是否为真。


你好!前两个是的,第三个在哪里?这是相应的HAR:https://gist.github.com/rolandschuetz/cd278a9489b5065a256d - Roland Schütz
如果XHR实例上的withCredentials不等于true,则设置省略凭据标志。凭据字段值是指可能存在或不存在于服务器响应中的Access-Control-Allow-Credentials头。换句话说,如果已发送并缓存了另一个类似的预检请求,但预检缓存中的匹配包括cookie而响应中没有Access-Control-Allow-Credentials=true,或者请求中未包含cookie但响应中包含Access-Control-Allow-Credentials=true,则不会查询预检缓存。 - Ray Nicholus
我并不完全确定我的理解是否正确,但我没有更好的解释。也许@monsur可以驳斥或确认我的理解... - Ray Nicholus
我想我理解了这个概念。如果有帮助的话,我会尝试一下。谢谢。 - Roland Schütz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接