3

我有一个基于 Django 1.11 的非常复杂的 webapp。前段时间用户开始报告他们正在获取“其他人的视图”——memcached 为他们提供了由装饰器缓存的 html,@cache_page(xx)而没有区分缓存宽限期内的会话。

经过进一步调查,我发现在某些情况下Vary: Cookie标头丢失并且提供了错误的“会话”。奇怪的是,它只在使用 curl 查询后端时显示(没有会话、用户等 -> 后端服务登录到缓存视图中)。

不幸的是,这个问题真的很难重现,有时会发生,有时不会。我什至从头开始构建一个简单的 Django 应用程序,看看是否可以检查原因。@cache_page观察到的是,当被删除或login_required添加时问题不会发生。

我最终从视图中删除了所有 @cache_page 装饰器,并且在生产中没有观察到该问题,但这是一种解决方法,我想知道是什么原因。

如果有人有任何提示可能是什么原因,将不胜感激!

4

1 回答 1

2

您可能遇到了这个开放的错误

由于视图装饰器首先在传出响应上运行,在响应中间件之前,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
于 2017-08-21T17:29:00.503 回答