2

::编辑::

@cache_control(no_cache=True, must_revalidate=True, no_store=True)FTW!!!!

Cache-Control: no-cache, no-store, must-revalidate 成功了。花了几个 IRC chan 并环顾四周,但最后我让它工作了。

::编辑::

我有一个视图,我在其中设置了@login_required,并且大部分情况下它是安全的,但是如果您查看了视图,然后注销并点击浏览器中的后退按钮,您可以再次查看内容而不会被询问登录。尽管如果您刷新页面,服务器将重定向您。

我的暂停是一个缓存问题,也许我需要告诉 chrome 不要将其存储在历史记录中。

例如,如果您查看发票然后注销,您可以通过在您的历史记录中选择该页面再次查看发票。

我已经尝试过这个问题,没有问题。firefox 要求您登录后端,所以它一定是浏览器问题。

4

4 回答 4

6

你是对的,这是缓存问题。

您可以使用cache_control装饰器在视图 [1] 上强制不缓存:

from django.views.decorators.cache import cache_control

@cache_control(no_cache=True, must_revalidate=True, no_store=True)
def func()
  #some code
  return

您还应该编写自己的替换装饰器,@login_required这样您就不需要在每个页面上都使用它们。

[1]注销后禁用浏览器“返回”按钮?

于 2012-03-08T22:10:35.667 回答
3

此行为是由Webkit浏览器中的一项非官方称为Page Cache的功能引起的,也称为后退/前进缓存。它控制当前浏览会话中先前页面发生的情况。Webkit 做了一些特别的事情,它“暂停”以前的页面。就好像上一页隐藏在另一个选项卡中一样;单击后退按钮就像将选项卡带到前台。页面仍然原样存在。这意味着没有网络请求,因此您的服务器逻辑永远不会被触及。

您会在 Safari 和 Chrome 中看到这种行为。查看 Network Inspector面板并在单击返回页面时观察网络流量。乍一看,它看起来像是一个请求。Safari 无助于消除实际上没有发出请求的观念。Chrome 更有礼貌,会告诉你页面是“(从缓存中)”加载的。在 Chrome 中,查看大小列或单击请求并查看标头选项卡中的状态代码。当然,另一个指标是“请求”在时间线中花费了多长时间(可能是 0 毫秒)。

这解释了行为......现在如何解决它。最好的解决方案可能只是在注销页面上提醒关闭浏览器窗口。

您已经正确地确定在 Django 方面您无能为力。缓存装饰器不会帮助你。不幸的是,似乎没有一个规范的答案来阻止页面缓存存储页面。它似乎也是一个不断变化的特性,所以现在的解决方案可能只是一个 hack,它不适用于更高版本的 Webkit。或者 Firefox 可能会创建一个具有不同实现的类似功能。

通过 HTTPS 为您的网站提供服务,cache-control: no-store或者cache-control: no-cache可以这样做,但它肯定是重手。一种可能的技巧是设置一个unload/onunload事件处理程序。

在这 两个Surfin 的 Safari 文章中阅读有关页面缓存行为和卸载 hack 建议的更多信息。

更新- @DigitalCake 发现Cache-Control:no-store有一些效果。在 Django 中,这是通过@cache_control(no_store=True)装饰视图来完成的。no store 适用于 Chrome (v17.0.963.66) - 页面未隐藏在页面缓存中,并且后退按钮会导致网络请求。Safari (v5.1.3) 中不起作用no store。这表明,即使在 Webkit 浏览器中,页面缓存的实现方式也不同。它还证明了当前的解决方法很可能是临时的黑客攻击。

于 2012-03-08T22:29:10.330 回答
0

我尝试了这个解决方案,它对我有用。

我已经把 Cashe 控制和登录都需要。

这是示例

from django.contrib.auth.decorators import login_required
from django.views.decorators.cache import cache_control

@cache_control(no_cache=True, must_revalidate=True, no_store=True)
@login_required(login_url='login')
def myview(request):
   return HttpResponse(render(request,'path_to_your_view.html'))
于 2019-03-23T08:51:51.973 回答
0

2020 年 3 月更新:除了已接受的答案之外,Django 3.0 文档还显示了一个never_cache装饰器。

Cache-Control: max-age=0, no-cache, no-store, must-revalidate, private在响应中添加了一个标头。

于 2020-03-01T19:11:40.933 回答