2010-06-11 171 views
72

我們的Django應用程序具有以下會話管理要求。由於在Django中處於非活動狀態,如何過期會話?

  1. 當用戶關閉瀏覽器時會話過期。
  2. 會話在一段時間不活動後過期。
  3. 檢測會話何時因不活動而到期並向用戶顯示適當的消息。
  4. 在閒置期結束前幾分鐘向即將到期的會話過期的用戶發出警告。隨着警告,爲用戶提供延長會話的選項。
  5. 如果用戶正在處理應用程序中不涉及向服務器發送的請求的長時間業務活動,則該會話不得超時。

在閱讀文檔,Django代碼和一些與此相關的博客文章後,我提出了以下實現方法。

要求1
這一要求很容易地通過設置SESSION_EXPIRE_AT_BROWSER_CLOSE爲True實現。

要求2
我已經看到了一些建議使用SESSION_COOKIE_AGE設置會話到期時間。但是這種方法有以下問題。

  • 即使用戶正在使用該應用程序,該會話也始終在SESSION_COOKIE_AGE結束時到期。 (這可以通過使用自定義中間件將會話過期設置爲SESSION_COOKIE_AGE來防止,或者通過將SESSION_SAVE_EVERY_REQUEST設置爲true來保存每個請求上的會話,但由於使用SESSION_COOKIE_AGE,下一個問題是不可避免的。)

  • 由於Cookie的工作方式,SESSION_EXPIRE_AT_BROWSER_CLOSE和SESSION_COOKIE_AGE是互斥的,即Cookie在瀏覽器關閉時或在指定的到期時間屆滿。如果使用SESSION_COOKIE_AGE,並且用戶在cookie過期之前關閉瀏覽器,則Cookie將被保留,並且重新打開瀏覽器將允許用戶(或任何其他人)進入系統而不需要重新進行身份驗證。

  • Django僅依賴存在的cookie來確定會話是否處於活動狀態。它不會檢查與會話一起存儲的會話過期日期。

以下方法可用於實現此要求並解決上述問題。

  • 請勿設置SESSION_COOKIE_AGE。
  • 將會話的終止日期設置爲每個請求的「當前時間+非活動時間段」。
  • 在SessionMiddleware中覆蓋process_request並檢查會話過期。如果會話已過期,請放棄該會話。

要求3
當我們檢測到會話已過期(在上面的定製SessionMiddleware),該請求的屬性集,以指示會話終結。該屬性可用於向用戶顯示適當的消息。

要求4
使用JavaScript來檢測用戶的活動,提供警告並延長會話的選項。如果用戶希望擴展,則向服務器發送保活脈衝以延長會話。

要求5
使用JavaScript來檢測用戶活動(長期的業務運營中),併發送永葆脈衝到服務器,以防止過期會話。


上面的實現方法看起來非常複雜,我想知道是否有更簡單的方法(特別是對於需求2)。

任何見解將不勝感激。

+1

+1用於提供詳細的解決方案 – Don 2012-06-07 15:55:52

+1

「由於Cookie的工作方式,SESSION_EXPIRE_AT_BROWSER_CLOSE和SESSION_COOKIE_AGE是互斥的,即cookie在到瀏覽器關閉時或在指定的到期時間到期,如果使用SESSION_COOKIE_AGE且用戶關閉瀏覽器在cookie過期之前,Cookie將被保留,並且重新打開瀏覽器將允許用戶(或任何其他人)進入系統而不需要重新進行身份驗證。「糾正我,如果我錯了,但在新的Django版本中,這似乎不再是真的嗎? (至少1.5+) – 2014-11-04 12:53:26

+0

有一箇中間件可以做你需要的東西。 [在github上](https://github.com/subhranath/django-session-idle-timeout)和[在pypi上](http://pypi.python.org/pypi/django-session-idle-timeout/1.3 .1) – gbutler 2013-02-12 22:50:32

回答

38

這是一個想法...在瀏覽器上關閉會話並使其與SESSION_EXPIRE_AT_BROWSER_CLOSE設置關閉。然後在每個請求的會話中設置一個時間戳,像這樣。

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

並添加一箇中間件來檢測會話是否過期。這樣的事情應該處理的整個過程......

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 

然後你就必須做出一些網址,並享有相關數據返回關於會話過期Ajax調用。

當用戶選擇爲「更新」的會議,可以這麼說,所有你所要做的就是設置requeset.session['last_activity']再次當前時間

顯然,這種代碼僅僅是一個開始......但它應該得到你在正確的道路

+0

我只是在懷疑這裏,但我不認爲'如果不request.is_ajax()'是完全安全的。不能得到持有該會話預先到期欺騙/發送ajax調用,並保持會話進行? – 2013-05-11 03:53:51

+2

@ notbad.jpeg:一般來說,「活動」很容易被欺騙。持有該會話並不斷髮送請求的人只是活躍的。 – RemcoGerlich 2014-08-15 07:38:00

+0

這是一個很好的答案。中間件是Django開發中一個未充分利用的工具。 – 2016-04-26 13:57:51

25

django-session-security上做到了這一點......

...有一個額外的要求:如果服務器不響應或者攻擊者斷開互聯網連接:應該反正過期。

Disclamer:我維護這個程序。但我一直在看這個線程一個很長很長的時間:)

+1

很酷的應用程序 - 很好的設計和精心打造。很好,乾淨的代碼...謝謝。 – nicorellius 2014-03-01 17:33:19

+1

也定期更新 - 謝謝jpic – datakid 2014-03-13 01:54:14

+0

如果用戶在他/她離開時關閉瀏覽器或選項卡(不註銷),是否仍強制用戶註銷?它處理這種情況嗎? – waterkinq 2016-04-05 11:40:01

3

在第一個請求,你可以設置會話有效期爲

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

並採用access_key和令牌時,

try: 
    key = self.request.session['access_key'] 
except KeyError: 
    age = self.request.session.get_expiry_age() 
    if age > set_age: 
     #redirect to login page 
+0

向上投票贊成缺乏評論downvoter。 – Ruraj 2016-02-26 12:52:47

9

滿足您的第二個要求的一個簡單方法是在設置中設置SESSION_COOKIE_AGE值。py到合適的秒數。例如:

SESSION_COOKIE_AGE = 600  #10 minutes. 

但是,僅通過執行此操作,會話將在10分鐘後過期,無論用戶是否展示某些活動。爲了解決這個問題,到期時間可以自動更新(再額外10分鐘),每次使用者用下面的句子任何種類的要求:

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

我只是非常新的使用Django。

我想讓會話過期,如果登錄的用戶關閉瀏覽器或處於空閒狀態(非活動超時)一段時間。當我找到它時,這個SOF問題首先出現了。感謝很好的回答,我查找了資源,以瞭解中間件在Django中的請求/響應週期中的工作方式。這非常有幫助。

我正準備將自定義中間件應用到我的代碼中,在這裏的最佳答案。但是我仍然有點懷疑,因爲這裏的最佳答案是在2011年進行了編輯。我花了更多時間從最近的搜索結果中搜索一點,並提出了簡單的方法。

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

我沒有檢查其他瀏覽器,但鉻。 1.即使設置了SESSION_COOKIE_AGE,關閉瀏覽器時會話過期。 2.僅當我閒置超過10秒時,會話過期。感謝SESSION_SAVE_EVERY_REQUEST,每當您發生新的請求時,它都會將會話和更新超時保存到期。

要更改此默認行爲,請將SESSION_SAVE_EVERY_REQUEST設置設置爲True。當設置爲True時,Django會在每個請求中將會話保存到數據庫。

請注意,會話cookie僅在創建或修改會話時發送。如果SESSION_SAVE_EVERY_REQUEST爲真,會話cookie將在每個請求中發送。

同樣,每次發送會話cookie時會更新會話cookie的部分。

django manual 1.10

我剛剛離開的回答使一些人誰是一種新的在Django像我不會花太多時間去找出解決辦法的一種方式我做到了。

+0

你是男人!感謝您的研究。 – 2017-08-11 07:49:39

相關問題