Comment expirer session en raison de l'inactivité à Django?

notre application Django a les exigences suivantes de gestion de session.

  1. les Sessions expirent lorsque l'utilisateur ferme le navigateur.
  2. Les Sessions
  3. expirent après une période d'inactivité.
  4. détecte quand une session expire en raison de l'inactivité et affiche le message approprié à l'utilisateur.
  5. avertissez les utilisateurs de l'expiration imminente de la session quelques minutes avant la fin de la période d'inactivité. Ainsi avec l'avertissement, fournir aux utilisateurs une option pour prolonger leur session.
  6. si l'utilisateur travaille sur une longue activité commerciale au sein de l'application qui n'implique pas l'envoi de requêtes au serveur, la session ne doit pas être interrompue.

après avoir lu la documentation, le code Django et quelques billets de blog liés à cela, j'ai trouvé la méthode de mise en œuvre suivante.

exigence 1

Cette exigence est facilement implémentée en définissant SESSION_EXPIRE_AT_BROWSER_CLOSE à True.

exigence 2

J'ai vu quelques recommandations pour utiliser SESSION_COOKIE_AGE pour définir la période d'expiration de la session. Mais cette méthode présente les inconvénients suivants.

  • la session expire toujours à la fin de la session même si l'utilisateur est utilisation active de l'application. (Ceci peut être évité en définissant l'expiration de la session à SESSION_COOKIE_AGE sur chaque requête en utilisant un middleware personnalisé ou en sauvegardant la session sur chaque requête en définissant SESSION_SAVE_EVERY_REQUEST à true. Mais le problème suivant est inévitable en raison de l'utilisation de SESSION_COOKIE_AGE.)

  • en raison de la façon dont les cookies fonctionnent, SESSION_EXPIRE_AT_BROWSER_CLOSE et SESSION_COOKIE_AGE s'excluent mutuellement, c'est-à-dire que le cookie soit expire fermeture du navigateur ou à l'heure d'expiration spécifiée. Si SESSION_COOKIE_AGE est utilisé et que l'utilisateur ferme le navigateur avant l'expiration du cookie, le cookie est conservé et la réouverture du navigateur permettra à l'utilisateur (ou à toute autre personne) d'entrer dans le système sans être ré-authentifié.

  • Django se base uniquement sur le cookie présent pour déterminer si la session est active. Il ne vérifie pas la date d'expiration de la session stockée avec la session.

la méthode suivante pourrait être utilisée pour mettre en œuvre cette exigence et pour contourner les problèmes mentionnés ci-dessus.

  • Do not set SESSION_COOKIE_AGE.
  • fixe la date d'expiration de la session à 'heure actuelle + période d'inactivité' sur chaque demande.
  • outrepasser process_request dans SessionMiddleware et vérifier l'expiration de la session. Rejeter la session si elle est Expirée.

exigence 3

Lorsque nous détectons que la session est Expirée (dans le custom SessionMiddleware ci-dessus), définissez un attribut sur la requête pour indiquer l'expiration de la session. Cet attribut peut être utilisé pour afficher un message approprié à l'utilisateur.

exigence 4

Utiliser JavaScript pour détecter l'inactivité de l'Utilisateur, fournir l'avertissement et aussi une option pour prolonger la session. Si l'Utilisateur souhaite prolonger, envoyer une impulsion garder en vie au serveur pour prolonger la session.

exigence 5

Utilisez JavaScript pour détecter l'activité de l'utilisateur (au cours de l'opération longue entreprise) et envoyer des impulsions garder en vie au serveur pour empêcher la session d'expirer.


L'approche de mise en œuvre ci-dessus semble très élaborée et j'ai été je me demande s'il pourrait y avoir une méthode plus simple (en particulier pour L'exigence 2).

toute perspicacité sera grandement appréciée.

78
demandé sur Akbar ibrahim 2010-06-11 19:39:04

6 réponses

Voici une idée... Expirez la session sur la fermeture du navigateur avec le paramètre SESSION_EXPIRE_AT_BROWSER_CLOSE . Ensuite, définissez un timestamp dans la session sur chaque requête comme ceci.

request.session['last_activity'] = datetime.now()

et Ajouter un middleware pour détecter si la session est Expirée. quelque chose comme ça devrait gérer tout le processus...

from datetime import datetime
from django.http import HttpResponseRedirect

class SessionExpiredMiddleware:
    def process_request(request):
        last_activity = request.session['last_activity']
        now = datetime.now()

        if (now - last_activity).minutes > 10:
            # Do logout / expire session
            # and then...
            return HttpResponseRedirect("LOGIN_PAGE_URL")

        if not request.is_ajax():
            # don't set this for ajax requests or else your
            # expired session checks will keep the session from
            # expiring :)
            request.session['last_activity'] = now

alors vous avez juste à faire quelques urls et vues pour retourner les données pertinentes aux appels ajax concernant l'expiration de la session.

quand l'utilisateur choisit de "renouveler" la session, pour ainsi dire, tout ce que vous avez à faire est de mettre requeset.session['last_activity'] à l'heure actuelle à nouveau

Évidemment, ce code n'est qu'un début... mais il devrait vous mettre sur la bonne voie

40
répondu Jiaaro 2010-06-11 18:45:08

django-session-sécurité ...

... avec une exigence supplémentaire: si le serveur ne répond pas ou si un attaquant déconnecte la connexion internet: elle devrait expirer de toute façon.

clause de non-responsabilité: je maintiens cette application. Mais j'ai été regarder ce fil de discussion pour une très longue période de temps :)

26
répondu jpic 2013-02-18 19:02:36

Je suis juste assez nouveau pour utiliser Django.

je voulais faire expirer la session si l'Utilisateur a fermé son navigateur ou est inactif(temps d'inactivité) pendant un certain temps. Quand je l'ai cherché sur Google, cette question Est Arrivée en premier. Grâce à nice answer, j'ai cherché des ressources pour comprendre comment fonctionne middlewares pendant le cycle de demande/réponse à Django. Il a été très utile.

j'étais sur le point d'appliquer middleware personnalisé dans mon code suivant haut de réponse ici. Mais j'étais encore un peu suspicieux car best answer ici a été édité en 2011. J'ai pris plus de temps pour chercher un peu à partir des résultats de recherche récents et est venu avec voie simple.

SESSION_EXPIRE_AT_BROWSER_CLOSE = True
SESSION_COOKIE_AGE = 10 # set just 10 seconds to test
SESSION_SAVE_EVERY_REQUEST = True

Je n'ai pas vérifié d'autres navigateurs mais chrome. 1. Une session a expiré lorsque j'ai fermé un navigateur, même si SESSION_COOKIE_AGE est défini. 2. Seulement quand j'étais inactif pendant plus de 10 Secondes, une session expirait. Merci à SESSION_SAVE_EVERY_REQUEST, chaque fois que vous vous produisez nouvelle requête, Il sauve la session et met à jour le délai d'expiration

pour modifier ce comportement par défaut, définissez le paramètre SESSION_SAVE_EVERY_REQUEST à True. Une fois défini à True, Django enregistrera la session dans la base de données sur chaque requête.

notez que le cookie de session n'est envoyé que lorsqu'une session a été créée ou modifiée. Si SESSION_SAVE_EVERY_REQUEST est True, le cookie de session sera envoyé sur chaque requête.

de même, la expires une partie d'un cookie de session est mise à jour chaque fois que le cookie de session est envoyé.

manuel de django 1.10

je laisse simplement answer pour que des gens qui sont un peu nouveaux à Django comme moi ne passent pas beaucoup de temps à trouver une solution comme je l'ai fait.

18
répondu Jayground 2016-10-19 02:49:55

un moyen facile de satisfaire votre deuxième exigence serait de définir la valeur de SESSION_COOKIE_AGE en settings.py à une quantité appropriée de secondes. Par exemple:

SESSION_COOKIE_AGE = 600      #10 minutes.

Cependant, en ne faisant cela que la session expirera après 10 minutes que l'utilisateur montre ou non une certaine activité. Pour traiter cette question, le temps d'expiration peut être automatiquement renouvelé (pour 10 minutes supplémentaires) chaque fois que l'utilisateur effectue un type de demande avec les suivants phrase:

request.session.set_expiry(request.session.get_expiry_age())
10
répondu Fernando Martin 2015-06-08 13:58:52

vous pouvez également utiliser stackoverflow construire dans les fonctions

SESSION_SAVE_EVERY_REQUEST = True
3
répondu mexekanez 2017-05-23 12:18:01

dans la première requête, vous pouvez définir l'expiration de la session comme

self.request.session['access_key'] = access_key
self.request.session['access_token'] = access_token
self.request.session.set_expiry(set_age) #in seconds 

et en utilisant access_key et token,

try:
    key = self.request.session['access_key']
except KeyError:
    age = self.request.session.get_expiry_age()
    if age > set_age:
        #redirect to login page
3
répondu tilaprimera 2015-04-25 04:22:04