Django'da hareketsizlik nedeniyle oturum nasıl sona erer?


97

Django uygulamamız aşağıdaki oturum yönetimi gereksinimlerine sahiptir.

  1. Kullanıcı tarayıcıyı kapattığında oturumların süresi dolar.
  2. Oturumlar, bir süre hareketsiz kaldıktan sonra sona erer.
  3. Etkinlik olmaması nedeniyle bir oturumun ne zaman sona erdiğini tespit edin ve kullanıcıya uygun mesajı görüntüleyin.
  4. Kullanıcıları, eylemsizlik süresinin bitiminden birkaç dakika önce sona ermesi konusunda uyarın. Uyarının yanı sıra, kullanıcılara oturumlarını uzatma seçeneği sunun.
  5. Kullanıcı, uygulama içinde sunucuya gönderilen istekleri içermeyen uzun bir iş etkinliği üzerinde çalışıyorsa, oturum zaman aşımına uğramamalıdır.

Belgeleri, Django kodunu ve bununla ilgili bazı blog yazılarını okuduktan sonra, aşağıdaki uygulama yaklaşımını buldum.

Gereksinim 1
Bu gereksinim, SESSION_EXPIRE_AT_BROWSER_CLOSE'u True olarak ayarlayarak kolayca uygulanabilir.

Gereksinim 2
Oturumun sona erme süresini ayarlamak için SESSION_COOKIE_AGE kullanmak için birkaç öneri gördüm. Ancak bu yöntemin aşağıdaki sorunları vardır.

  • Kullanıcı uygulamayı aktif olarak kullanıyor olsa bile, oturum her zaman SESSION_COOKIE_AGE sonunda sona erer. (Bu, özel bir ara yazılım kullanarak her istekte oturumun sona ermesini SESSION_COOKIE_AGE olarak ayarlayarak veya SESSION_SAVE_EVERY_REQUEST'i true olarak ayarlayarak oturumu her istekte kaydederek önlenebilir. Ancak SESSION_COOKIE_AGE kullanımı nedeniyle bir sonraki sorun kaçınılmazdır.)

  • Çerezlerin çalışma şekli nedeniyle, SESSION_EXPIRE_AT_BROWSER_CLOSE ve SESSION_COOKIE_AGE birbirini dışlar, yani çerez ya tarayıcı kapandığında ya da belirtilen süre sonunda sona erer. SESSION_COOKIE_AGE kullanılırsa ve kullanıcı, çerezin süresi dolmadan tarayıcıyı kapatırsa, çerez saklanır ve tarayıcının yeniden açılması, kullanıcının (veya başka birinin) yeniden kimlik doğrulaması yapılmadan sisteme girmesine izin verir.

  • Django, oturumun aktif olup olmadığını belirlemek için yalnızca mevcut tanımlama bilgisine güvenir. Seansla kaydedilen seans bitiş tarihini kontrol etmez.

Bu gereksinimi uygulamak ve yukarıda bahsedilen sorunları çözmek için aşağıdaki yöntem kullanılabilir.

  • SESSION_COOKIE_AGE ayarlamayın.
  • Her talepte oturumun sona erme tarihini 'geçerli zaman + hareketsizlik süresi' olarak ayarlayın.
  • SessionMiddleware'de process_request'i geçersiz kılın ve oturumun sona ermesini kontrol edin. Süresi dolmuşsa oturumu iptal edin.

Gereksinim 3
Oturumun sona erdiğini tespit ettiğimizde (yukarıdaki özel SessionMiddleware'de), oturumun sona erdiğini belirtmek için istek üzerine bir öznitelik ayarlayın. Bu özellik, kullanıcıya uygun bir mesaj görüntülemek için kullanılabilir.

Gereksinim 4
Kullanıcının hareketsizliğini algılamak, uyarı sağlamak ve ayrıca oturumu uzatmak için bir seçenek sağlamak için JavaScript kullanın. Kullanıcı uzatmak isterse, oturumu uzatmak için sunucuya canlı tutma darbesi gönderin.

Gereksinim 5
Kullanıcı etkinliğini algılamak için JavaScript kullanın (uzun iş operasyonu sırasında) ve oturumun süresinin dolmasını önlemek için sunucuya canlı tutma darbeleri gönderin.


Yukarıdaki uygulama yaklaşımı çok ayrıntılı görünüyor ve daha basit bir yöntem olup olmadığını merak ediyordum (özellikle Gereksinim 2 için).

Herhangi bir anlayış çok takdir edilecektir.


3
Ayrıntılı bir çözüm sağlamak için +1
Don

İhtiyacınız olanı yapabilecek bir ara yazılım var. github ve on pypi
gbutler

1
"Çerezlerin çalışma şekli nedeniyle, SESSION_EXPIRE_AT_BROWSER_CLOSE ve SESSION_COOKIE_AGE birbirini dışlar, yani çerez tarayıcı kapandığında veya belirtilen süre dolduğunda sona erer. SESSION_COOKIE_AGE kullanılırsa ve kullanıcı çerezin süresi dolmadan tarayıcıyı kapatırsa, çerez saklanır ve yeniden açılır tarayıcı, kullanıcının (veya başka birinin) yeniden kimlik doğrulaması yapılmadan sisteme girmesine izin verecektir. " Yanılıyorsam düzelt ama bu daha yeni Django sürümlerinde artık doğru görünmüyor? (En az 1.5+)
Botond Béres

1
"Django, oturumun etkin olup olmadığını belirlemek için yalnızca mevcut tanımlama bilgisine güvenir. Oturumda depolanan oturumun sona erme tarihini kontrol etmez." Bu artık doğru değil.
knaperek

2020'de ikinci cevap kabul edilen cevap olmalıdır. Şu anda kabul edilen, Django'da zaten uygulanan bir şey için karmaşıklık katıyor.
WhyNotHugo

Yanıtlar:


44

İşte bir fikir ... Ayarla birlikte tarayıcı kapatıldığında oturumu sona SESSION_EXPIRE_AT_BROWSER_CLOSEerdirin. Ardından, her istek üzerine oturumda bir zaman damgası belirleyin.

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

ve oturumun süresinin dolup dolmadığını algılamak için bir ara yazılım ekleyin. bunun gibi bir şey tüm süreci ele almalı ...

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

Ardından, oturumun sona ermesiyle ilgili ajax çağrılarına ilgili verileri döndürmek için bazı url'ler ve görünümler oluşturmanız yeterlidir.

kullanıcı oturumu "yenilemeyi" tercih ettiğinde, tabiri caizse, tek yapmanız gereken requeset.session['last_activity']tekrar geçerli saate ayarlamaktır

Açıkçası bu kod sadece bir başlangıç ​​... ama sizi doğru yola götürmeli


Burada şüpheliyim ama if not request.is_ajax()tamamen güvenli olduğunu sanmıyorum . Oturumu elinde tutan biri sona ermeden önce sahtekarlık yapamaz / ajax çağrısı gönderip oturumu devam ettiremez mi?
notbad.jpeg

2
@ notbad.jpeg: genel olarak "etkinlik" kolayca yanıltılabilir. Oturumu ele geçiren ve istek göndermeye devam eden biri sadece aktiftir.
RemcoGerlich

Bu harika bir cevap. Ara yazılım, Django geliştirmede çok az kullanılan bir araçtır.
Jamie Counsell

37

Django'yu kullanmak için oldukça yeniyim.

Oturum açmış kullanıcı tarayıcıyı kapatırsa veya bir süre boşta kalırsa (hareketsizlik zaman aşımı) oturumun sona ermesini istedim. Bunu anlamak için Google'da araştırdığımda, önce bu SOF sorusu geldi. Güzel cevap sayesinde, Django'da istek / yanıt döngüsü sırasında ara yazılımların nasıl çalıştığını anlamak için kaynakları araştırdım. Çok yardımcı oldu.

Buradaki en iyi yanıtı takiben koduma özel ara yazılım uygulamak üzereydim. Ama yine de biraz şüpheliydim çünkü buradaki en iyi cevap 2011'de düzenlendi. Son arama sonuçlarından biraz daha fazla arama yapmak için biraz daha zaman harcadım ve basit bir yol buldum.

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

Diğer tarayıcıları kontrol etmedim ama Chrome. 1. SESSION_COOKIE_AGE ayarlanmış olsa bile bir tarayıcıyı kapattığımda bir oturumun süresi doldu. 2. Yalnızca 10 saniyeden fazla boşta kaldığımda, Bir oturumun süresi doldu. SESSION_SAVE_EVERY_REQUEST sayesinde, her yeni istek oluştuğunda, oturumu kaydeder ve süresi dolmak için zaman aşımını günceller

Bu varsayılan davranışı değiştirmek için SESSION_SAVE_EVERY_REQUEST ayarını True olarak ayarlayın. True olarak ayarlandığında, Django her istekte oturumu veritabanına kaydedecektir.

Oturum tanımlama bilgisinin yalnızca bir oturum oluşturulduğunda veya değiştirildiğinde gönderildiğini unutmayın. SESSION_SAVE_EVERY_REQUEST True ise, oturum çerezi her talepte gönderilecektir.

Benzer şekilde, bir oturum tanımlama bilgisinin sona eren kısmı, oturum tanımlama bilgisi her gönderildiğinde güncellenir.

django kılavuzu 1.10

Benim gibi Django'da yeni olan bazı insanlar benim yaptığım gibi çözüm bulmak için fazla zaman harcamasın diye cevap bırakıyorum.


26

django-session-security tam da bunu yapar ...

... ek bir gereksinimle: sunucu yanıt vermezse veya bir saldırgan internet bağlantısını kestiyse: yine de süresi dolmalıdır.

Disclamer: Bu uygulamanın bakımını yapıyorum. Ama bu konuyu çok çok uzun zamandır izliyorum :)


1
harika uygulama - güzel tasarlanmış ve iyi inşa edilmiş. güzel, temiz kod ... teşekkür ederim.
nicorellius

Kullanıcı çıkarken tarayıcıyı veya sekmeyi kapatırsa (oturumu kapatmadan), yine de kullanıcıyı çıkış yapmaya zorluyor mu? Bu durumu ele alıyor mu?
Mehmet Kağan Kayaalp

Bu, saf http oturum tanımlama bilgisinin sona ermesiyle ele alınır, değil mi?
jpic

12

İkinci gereksinimi karşılamanın kolay bir yolu, settings.py'deki SESSION_COOKIE_AGE değerini uygun bir saniye miktarına ayarlamaktır. Örneğin:

SESSION_COOKIE_AGE = 600      #10 minutes.

Ancak, yalnızca bunu yaptığınızda, kullanıcı bazı aktiviteler sergileyip sergilemese de oturum 10 dakika sonra sona erecektir. Bu sorunu çözmek için, kullanıcı aşağıdaki cümle ile herhangi bir talepte bulunduğunda sona erme süresi otomatik olarak yenilenebilir (fazladan 10 dakika daha):

request.session.set_expiry(request.session.get_expiry_age())

2
SESSION_COOKIE_AGE = 600 Bu, her yeni sayfa isteği veya sayfa yenilemesiyle oturumların yaşını uzatacak
2018'de saat

1
Sadece ayarın SESSION_COOKIE_AGEyeterli olduğunu ve herhangi bir isteğin (oturum tanımlama bilgisini göndermek) oturum tanımlama bilgisinin son kullanma tarihini otomatik olarak yenileyeceğini onaylıyorum .
bruno desthuilliers


3

İlk istekte, oturumun sona ermesini şu şekilde ayarlayabilirsiniz:

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

Ve erişim anahtarını ve jetonu kullanırken,

try:
    key = self.request.session['access_key']
except KeyError:
    age = self.request.session.get_expiry_age()
    if age > set_age:
        #redirect to login page
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.