web-dev-qa-db-ja.com

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をオーバーライドし、セッションの有効期限を確認します。セッションの有効期限が切れた場合は破棄してください。

要件
セッションの有効期限が切れたことを検出したら(上記のカスタムSessionMiddlewareで)、リクエストに属性を設定して、セッションの有効期限を示します。この属性を使用して、適切なメッセージをユーザーに表示できます。

要件4
JavaScriptを使用して、ユーザーの非アクティブを検出し、警告を提供し、セッションを延長するオプションも提供します。ユーザーが延長したい場合は、キープアライブパルスをサーバーに送信してセッションを延長します。

要件5
JavaScriptを使用して(長時間のビジネスオペレーション中に)ユーザーアクティビティを検出し、キープアライブパルスをサーバーに送信して、セッションが期限切れにならないようにします。


上記の実装アプローチは非常に精巧であるように見え、より簡単な方法があるのではないかと思っていました(特に要件2)。

洞察は非常に高く評価されます。

84
Akbar ibrahim

ここにアイデアがあります...ブラウザでセッションを終了するには、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呼び出しに関連データを返すために、いくつかのURLとビューを作成する必要があります。

ユーザーがセッションを「更新」することを選択した場合、いわば、あなたがしなければならないことはrequeset.session['last_activity']再び現在の時刻に

明らかに、このコードは開始点にすぎません...しかし、正しい道を歩むはずです

41
Jiaaro

Django-session-security はまさにそれを行います...

...追加要件:サーバーが応答しないか、攻撃者がインターネット接続を切断した場合:とにかく期限切れになるはずです。

Disclamer:このアプリをメンテナンスしています。しかし、私は非常に長い間このスレッドを見てきました:)

26
jpic

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がTrueの場合、セッションCookieはリクエストごとに送信されます。

同様に、セッションCookieの有効期限部分は、セッションCookieが送信されるたびに更新されます。

Djangoマニュアル1.1

私のようなDjango=の新しい人が、私がしたように解決策を見つけるのに多くの時間を費やさないように、私はただ答えを残します。

25
Jayground

2番目の要件を満たす簡単な方法の1つは、settings.pyのSESSION_COOKIE_AGE値を適切な秒数に設定することです。例えば:

SESSION_COOKIE_AGE = 600      #10 minutes.

ただし、これを行うだけで、ユーザーが何らかのアクティビティを示すかどうかにかかわらず、セッションは10分後に期限切れになります。この問題に対処するために、ユーザーが次の文を使用して何らかの種類の要求を実行するたびに、有効期限を自動的に更新することができます(さらに10分間)。

request.session.set_expiry(request.session.get_expiry_age())
10
Fernando Martin

最初のリクエストでは、セッションの有効期限を次のように設定できます。

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
3
tilaprimera

また、 stack overflow built in functions を使用することもできます

SESSION_SAVE_EVERY_REQUEST = True
3
mexekanez