我有一个基于Django 1.11的非常复杂的webapp。
前段时间,用户开始报告他们正在获取其他人的观点' - memcached为它们提供了由装饰器@cache_page(xx)
缓存的html,而不区分缓存宽限期内的会话。
经过进一步调查,我发现在某些情况下,Vary: Cookie
标题丢失,错误的“会话”#39;送达了。有什么奇怪的,它只在用curl查询后端时显示(没有会话,用户等 - >后端服务登录缓存视图)。
不幸的是,这个问题很难重现,有时它会发生,有时它并不存在。我甚至从头开始构建一个简单的Django应用程序,看看我是否可以检查是什么原因。
观察到的是,删除@cache_page
或添加login_required
时不会出现此问题。
我最终从视图中删除了所有@cache_page装饰器,但是在生产中没有发现问题,但它是一种解决方法,我想知道原因是什么。
如果有人有任何暗示可能是什么原因,我们将不胜感激!
答案 0 :(得分:2)
你可能遇到了这个open bug:
由于视图装饰器首先在传出响应上运行,因此在响应中间件之前,
cache_page
装饰器会在任何提到的响应中间件有机会添加其Vary标头之前缓存响应。这意味着两件事:1)使用的缓存密钥不包括响应应该变化的标头,Django可能稍后将响应提供给真正不应该获得它的用户,以及2)当缓存的响应稍后时服务于用户时,它仍然不会包含它应该具有的Vary
标头,因此也可能被上游HTTP缓存错误地缓存。
换句话说,在缓存响应时,SessionMiddleware
还没有机会设置Vary: Cookie
标头,因此所有会话将共享相同的缓存密钥。
您可以通过明确指定Vary
标头来解决此问题。例如:
from django.views.decorators.cache import cache_page
from django.views.decorators.vary import vary_on_cookie
@cache_page()
@vary_on_cookie()
def my_view():
pass