Представления Django @login_required по-прежнему отображаются, когда пользователи выходят из системы, возвращаясь в историю в Chrome.

::Редактировать::

@cache_control(no_cache=True, must_revalidate=True, no_store=True) ФТВ!!!!!

Cache-Control: no-cache, no-store, must-revalidate сделали свое дело. Потребовалось посетить несколько IRC-каналов и осмотреться, но, наконец, у меня все заработало.

::РЕДАКТИРОВАТЬ::

У меня есть представление, в котором я устанавливаю @login_required, и оно по большей части безопасно, но если вы просмотрели представление, затем выйдите из системы и просто нажмите кнопку «Назад» в своем браузере, вы можете снова просмотреть содержимое без запроса чтобы залогиниться. Хотя, если вы обновите страницу, сервер перенаправит вас.

Моя приостановка связана с проблемой кеша, и, возможно, мне нужно сказать хрому, чтобы он не сохранял ее в истории.

например, если вы просматриваете счет-фактуру, а затем выходите из системы, вы можете снова просмотреть счет-фактуру, выбрав эту страницу в своей истории.

Я пробовал эту проблему или firefox без проблем. firefox просит вас войти в систему, так что это должно быть проблемой браузера.


person Polygon Pusher    schedule 08.03.2012    source источник
comment
Отображение страницы в истории браузера не имеет никакого отношения к login_required. Это все равно проявится. Однако страница не должна загружаться, как если бы пользователь вошел в систему, когда это не так. Если это происходит, это совсем другой вопрос.   -  person Chris Pratt    schedule 09.03.2012
comment
Извините, что не был более осведомлен о проблеме. Я описал это настолько хорошо, насколько я понял проблему. Несмотря на это, я чувствую, что после нажатия кнопки «Назад» содержимое не должно отображаться, если пользователь больше не вошел в систему, что не является проблемой для Firefox.   -  person Polygon Pusher    schedule 09.03.2012
comment
Здесь есть очень похожий вопрос: stackoverflow.com/questions/6923027/   -  person Marius Grigaitis    schedule 09.03.2012
comment
Вы отредактировали этот вопрос, чтобы поместить ответ в вопрос? Болезненный. Почему бы просто не отредактировать его, чтобы он был ясным, и оставить принятый ответ в качестве ответа?   -  person eric    schedule 01.09.2017


Ответы (4)


Вы правы, это проблема с кешем.

Вы можете использовать декоратор 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] Отключить кнопку "Назад" в браузере после выхода из системы?

person Marius Grigaitis    schedule 08.03.2012
comment
Итак, я проверил, что действительно есть Cache-Control: no-cache, must-revalidate в заголовке, но все равно показывает страницу независимо. это с использованием @cache_control(no_cache=True, must_revalidate=True), и я пробовал @never_cache - person Polygon Pusher; 09.03.2012
comment
очень близко, спасибо за помощь, хотя. Я обнаружил, что @cache_control(no_cache=True, must_revalidate=True, no_store=True) работает. - person Polygon Pusher; 09.03.2012
comment
Отредактировал ответ, как предложил Digital Cake - person Marius Grigaitis; 09.03.2012
comment
Очень полезно, но меня интересует You should also write your own decorator that replaces @login_required so that you don't need to use both on every page. Хотя это может дать немного DRY, возможно, это сделает код менее читаемым. Кажется, очень легко иметь двух маленьких декораторов. Вы видели, как это делается, или делали это сами (т.е. объединили два декоратора в один)? Мне было бы очень любопытно увидеть простейший код для этого. - person eric; 03.09.2017

Такое поведение вызвано функцией браузеров Webkit, неофициально называемой Кэш страниц, также известной как возвратный/прямой кеш. Он контролирует, что происходит с предыдущими страницами в текущем сеансе просмотра. Webkit делает что-то особенное в том, что он «приостанавливает» предыдущие страницы. Как будто предыдущая страница скрыта в другой вкладке; нажатие кнопки «Назад» похоже на перенос вкладки на передний план. Страница осталась такой же, как и была. Это означает, что сетевой запрос не выполняется, и поэтому логика вашего сервера никогда не затрагивается.

Вы увидите это поведение как в Safari, так и в Chrome. Посмотрите на панель Network Inspector и наблюдайте за сетевым трафиком, когда вы нажимаете < em>вернуться на страницу. На первый взгляд похоже, что запрос был сделан. Safari не помогает развеять представление о том, что на самом деле никакого запроса не было. Chrome более вежлив и сообщает вам, что страница была загружена «(из кеша)». В Chrome посмотрите на столбец размер или щелкните запрос и посмотрите на Код состояния на вкладке Заголовки. Конечно, другим показателем является то, сколько времени занял «запрос» на временной шкале (вероятно, 0 мс).

Это объясняет поведение... теперь, как обойти это. Лучшим решением может быть просто напоминание на странице выхода о необходимости закрыть окно браузера.

Вы правильно определили, что на стороне Django вы ничего не можете сделать. Декораторы кеша вам не помогут. К сожалению, не существует канонического ответа на то, как предотвратить сохранение страницы кэшем страниц. Похоже, что эта функция находится в постоянном развитии, поэтому решение сейчас может быть просто хаком, который не будет работать в более поздних версиях Webkit. Или Firefox может создать аналогичную функцию с другой реализацией.

Обслуживание вашего сайта через HTTPS с помощью cache-control: no-store или cache-control: no-cache может помочь, но это точно тяжело. Одним из возможных способов взлома может быть установка обработчика событий unload/onunload.

Узнайте больше о поведении Page Cache и предложении по удалению хака на эти два Статьи Surfin' Safari.

ОБНОВЛЕНИЕ. @DigitalCake обнаружил, что Cache-Control:no-store имеет некоторый эффект. В Django это достигается с помощью @cache_control(no_store=True) украшения представления. no store работает в Chrome (v17.0.963.66) — страница не сохраняется в кэше страниц, а кнопка «Назад» вызывает сетевой запрос. no store не работает в Safari (v5.1.3). Это показывает, что даже в браузерах Webkit кэш страниц реализован по-разному. Это также демонстрирует тот факт, что текущие обходные пути, скорее всего, будут временными хаками.

person JCotton    schedule 08.03.2012
comment
Это отстой, потому что есть Cache-Control: no-cache, must-revalidate заголовок уже. - person Polygon Pusher; 09.03.2012
comment
Кэш страницы назад/вперед не является настоящим кешем — он просто приостанавливает страницу — поэтому он не следует правилам управления кешем. - person JCotton; 09.03.2012

Я попробовал это решение, и оно сработало для меня.

Я установил и контроль кассы, и вход в систему.

Вот пример

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'))
person Mahmood    schedule 23.03.2019

Обновление за март 2020 г.: в дополнение к принятому ответу в документах Django 3.0 показан декоратор never_cache.

Он добавляет к ответу заголовок Cache-Control: max-age=0, no-cache, no-store, must-revalidate, private.

person mark_s    schedule 01.03.2020