Django @login_required views still show when users are logged out by going back in history on Chrome

淺唱寂寞╮ 提交于 2019-12-04 15:47:15

问题


::Edit::

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

Cache-Control: no-cache, no-store, must-revalidate did the trick. It took going to a few IRC chans and looking around but finally I got it to work.

::EDIT::

I have a view where I'm setting @login_required on it and its secure for the most part, but if you have looked at the view then logout and just hit the back button in your browser you can view the content again with out being asked to login. Though if you refresh the page the server with will redirect you.

My suspension is its a cache issue where maybe I need to tell chrome not to store it in the history.

if you view a invoice for example then logout you can view the invoice again by selecting that page in your back history.

I have tried this issue o firefox with no problem. firefox asks for you to log back end so it must be a browser issue.


回答1:


You're right, this is cache problem.

You can use cache_control decorator to force no cache on views[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

You should also write your own decorator that replaces @login_required so that you don't need to use both on every page.

[1] Disable browser 'Back' button after logout?




回答2:


This behavior is caused by a feature in Webkit browsers unofficially called Page Cache, also known as the back/forward cache. It controls what happens to previous pages in the current browsing session. Webkit does something special in that it "suspends" previous pages. It's as if the previous page is hidden in another tab; clicking the back button is like bringing the tab into the foreground. The page is still there just as it was. This means no network request is made and therefore your server logic is never touched.

You'll see this behavior in Safari as well as Chrome. Look at the Network Inspector panel and watch the network traffic when you click back to a page. At a glance it looks like a request was made. Safari doesn't help dispel the notion that no request was actually made. Chrome is more polite and tells you the page was loaded "(from cache)". In Chrome, look at the size column or click the request and look at the Status Code in the Headers tab. Of course the other indicator is how long the 'request' took in the Timeline (probably 0ms).

That explains the behavior...now how to get around it. The best solution may just be a reminder on the logout page to close the browser window.

You've correctly determined that there's nothing you can do on the Django side. The cache decorators won't help you. Unfortunately there doesn't appear to be a canonical answer to preventing Page Cache from stashing a page. It also seems to be a feature in flux, so a solution now may just be a hack that won't work on later versions of Webkit. Or Firefox may create a similar feature with different implementation.

Serving your site over HTTPS with cache-control: no-store or cache-control: no-cache may do it but it's heavy handed for sure. One possible hack would be to set an unload/onunload event handler.

Read more about Page Cache behavior and the unload hack suggestion on these two Surfin' Safari articles.

UPDATE - @DigitalCake found that Cache-Control:no-store has some effect. In Django, this is accomplished with @cache_control(no_store=True) decorating the view. no store works in Chrome (v17.0.963.66) - the page is not stashed in Page Cache and the back button causes a network request. no store does not work in Safari (v5.1.3). This shows that even across Webkit browsers Page Cache is implemented differently. It demonstrates also the point that current work arounds are likely to be temporary hacks.




回答3:


I tried this solution and it worked for me.

I had put both cashe control and login required.

Here is the example

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'))


来源:https://stackoverflow.com/questions/9625046/django-login-required-views-still-show-when-users-are-logged-out-by-going-back

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!