我正经历着我的客户在向我的服务器提出一个无辜的请求后被注销。我控制两端,经过大量调试后,我发现发生了以下情况:
304 Not Modified进行响应。据我所知,浏览器不能缓存任何包含授权的请求。尽管如此,
chrome://view-http-cache/http://localhost:10080/api/SearchHost显示
HTTP/1.1 200 OK
Date: Thu, 23 Nov 2017 23:50:16 GMT
Vary: origin, accept-encoding, authorization, x-role
Cache-Control: must-revalidate
Server: 171123_073418-d8d7cb0 =
x-delay-seconds: 3
Authorization: Wl6pPirDLQqWqYv
Expires: Thu, 01 Jan 1970 00:00:00 GMT
ETag: "zUxy1pv3CQ3IYTFlBg3Z3vYovg3zSw2L"
Content-Encoding: gzip
Content-Type: application/json;charset=utf-8
Content-Length: 255有趣的服务器头用一些内部信息代替Jetty服务器头(出于安全原因不应该使用它)--忽略它。卷曲是这么说的:
< HTTP/1.1 304 Not Modified
< Date: Thu, 23 Nov 2017 23:58:18 GMT
< Vary: origin, accept-encoding, authorization, x-role
< Cache-Control: must-revalidate
< Server: 171123_073418-d8d7cb0 =
< ETag: "zUxy1pv3CQ3IYTFlBg3Z3vYovg3zSw2L"
< x-delay-seconds: 3
< Content-Encoding: gzip这种情况也发生在Firefox中,尽管我目前无法复制它。RFC继续说,看起来上面链接的答案并不准确:
除非响应中存在允许存储此类响应的缓存指令。
看起来响应是可缓存的。这很好,我确实希望缓存内容,但我不希望从缓存中为授权头提供服务。这个是可能的吗?
解释我的问题
我的服务器过去只在响应登录请求时才发送Authorization头。这过去工作得很好,新的要求带来了问题。
我们的网站允许用户任意长时间登录(我们不做敏感业务)。我们正在更改授权令牌的格式,因此我们不希望强迫所有用户再次登录。因此,每当服务器看到过时但有效的授权令牌时,它就会发送更新的授权令牌。因此,现在任何响应都可能包含授权令牌,但大多数响应不包含授权令牌。
浏览器缓存结合了仍然有效的响应和过时的授权令牌。
作为解决办法,我让服务器在出现授权令牌时不发送etag。很管用,但我更喜欢一些更干净的解决方案。
发布于 2017-12-03 21:30:03
链接答案中的引用具有误导性,因为它忽略了一个重要部分:“如果缓存是共享的”。以下是正确的引号(RFC7234第3节):
缓存不能存储对任何请求的响应,除非:授权头字段(见RFC7235的4.2节)不会出现在请求中,如果缓存是共享的,则为,
RFC的这一部分基本上是一个总结。这是一个完整的规则(RFC7234 3.2节),它本质上讲的是相同的东西:
共享缓存不能使用带有授权头字段(RFC7235第4.2节)的请求的缓存响应来满足任何后续请求,除非响应中存在允许存储此类响应的缓存指令。
浏览器缓存是共享缓存吗?这在RFC导言部分中有解释
相反,私有缓存专用于单个用户;它们通常作为用户代理(用户代理的一个组件)部署。
这意味着浏览器缓存是私有缓存。这不是一个共享缓存,所以上面的规则不适用,这意味着Chrome和Firefox都正确地完成了他们的工作。
现在解决办法。
该规范建议在没有授权头的情况下重用包含授权的缓存响应的可能性。不幸的是,它也说这个特性没有得到广泛的实现。
所以,我能想到的最简单也是最有前途的解决方案就是确保没有缓存任何包含授权令牌的响应。例如,每当服务器看到一个过时但有效的授权令牌时,将一个新的有效令牌与Cache-Control: no-store一起发送,以禁止缓存。
此外,您绝不能发送带有授权头的Cache-Control: must-revalidate,因为must-revalidate指令实际上允许缓存响应,包括通过共享缓存来缓存响应,这可能会在将来造成更多的问题。
..。除非响应中存在允许存储此类响应的缓存指令。 在本规范中,以下缓存控制响应指令(第5.2.2节)具有这样的效果:must-revalidate,公共和s-maxage。
发布于 2017-12-10 23:54:54
我的当前解决方案是在每个响应中发送一个授权头;当不需要授权时,使用-的占位符值。
占位符值显然是没有意义的,客户端知道它,并且很高兴地忽略它。
这个解决方案很难看,因为它为每个响应增加了大约20个字节,但这仍然比偶尔重新发送整个响应内容要好,就像我在问题中提到的方法一样。此外,对于HTTP/2,它将是免费的。
https://stackoverflow.com/questions/47464893
复制相似问题