Django session_data を定期的に削除する


session_data テーブルの削除設定を行っていなかったので、設定します。
デフォルト挙動知らずになんとなく使っておりました。


前提

以下の環境で作業は実施しています。

  • OS

    % sw_vers 
    ProductName:    Mac OS X
    ProductVersion: 10.12.6
    BuildVersion:   16G29
    

  • pythonのverion

    % python -V
    Python 2.7.10   
    

  • django の version

    % pip list | grep Django
    Django (1.10.7)
    


参考

以下、参考になりました。詳しく日本語で解説されています。

以下、1.11の公式ドキュメントのsetinngs.pyに設定できるsession関連の設定値へのリンクになります。
* Settings | Django documentation | Django


デフォルト動作

以下、デフォルト動作について記載します。

  • デフォルトON

  • 保存先はDB
    settings.py で default で使っているDBが使われます。

  • 期限切れのsession情報の扱い
    何もしない。
    そのままだと、残り続けます。 後述のclearsessions コマンドは用意されておりますが、「アプリケーションによって不要になるタイミングは異なる可能性がある」ため、デフォルトで削除が自動で行われません。

settings.pyでコントロール可能な値について

Settings | Django documentation | Django を参考に表にしてみました。

キー値内容デフォルト値
SESSION_CACHE_ALIASどのデータベース設定を使うかを設定する'default'
SESSION_COOKIE_AGEcookieの有効期間1209600 (2週間)
SESSION_COOKIE_DOMAINcookieをどのスコープで設定するかNone (2週間)
SESSION_COOKIE_HTTPONLYcookieにHTTPONLY属性を付与するか否かTrue(付与する)
SESSION_COOKIE_PATHcookieのパス'/'
SESSION_COOKIE_NAMEcookieの名称sessionid
SESSION_COOKIE_SECUREcookieのsecure属性値False
SESSION_ENGINEどこにセッションデータを登録するかを制御する'django.contrib.sessions.backends.db'
SESSION_EXPIRE_AT_BROWSER_CLOSEcookieのsession属性値False
SESSION_FILE_PATHファイルにセッションを登録する場合のファイルパスを指定するNone
SESSION_SAVE_EVERY_REQUESTセッションデータをリクエスト毎に保存するか否かFalse
SESSION_SERIALIZERSession情報をシリアライズする際の、シリアライザーの指定'django.contrib.sessions.serializers.JSONSerializer'

以下に気なったところに対するコメントです。

  • SESSION_EXPIRE_AT_BROWSER_CLOSE
    このブログはTrueにしています。

  • *SESSION_CACHE_ALIASと、SESSION_ENGINE の関係 *
    SESSION_CACHE_ALIAS には、settings.py の DATABASE エンジンのエイリアス名、
    SESSION_ENGINE には、エイリアスのストレージ対応した値を設定する必要があります。

  • SESSION_ENGINE
    Sessin engine として以下が設定可能です。
    cookiesにユーザー情報を保存して大丈夫なのかと思いましたが、暗号化して値を設定するようで、解読される危険性はありますがそれなりに安全そうです。

    • ‘django.contrib.sessions.backends.db’

    • ‘django.contrib.sessions.backends.file’

    • ‘django.contrib.sessions.backends.cache’

    • ‘django.contrib.sessions.backends.cached_db’

    • ‘django.contrib.sessions.backends.signed_cookies’


期限切れのsession_dataを削除する

削除コマンドについて

django の session には clearsessions コマンドが用意されています。
このコマンドを使用して、sessionテーブルのデータ削除を行います。
How to use sessions | Django documentation | Django
に記載がありますが、このコマンドを叩くと、clear_expired メソッドと同等の処理が行われます。
この処理はsessionのバックエンドにより、処理が異なり、db.pyとcache.pyでは以下のような実装になっています。
* django/django/contrib/sessions/backends/db.py

    @classmethod
    def clear_expired(cls):
        cls.get_model_class().objects.filter(expire_date__lt=timezone.now()).delete()

  • django/django/contrib/sessions/backends/cache.py
        @classmethod
        def clear_expired(cls):
            pass
    

現在、RDBがバックエンドですので、現在日付より前の有効期限を持つセッションを削除する となります。
ログイン状態で画面をしばらく放置しているユーザーがいたとして、このコマンド実行したらどうなるのだろうと思ったのですが、作成日ではなく有効期限なのでログイン状態のユーザーには有効期限がよっぽど短く無い限り影響はないのかと思います。

コマンドの実行

  • コマンド実行前にデータの確認

    python2.7 manage.py dbshell
    
    select count(*) from django_session;
    ------------------------------------------------
     count 
    -------
        46
    (1 )
    ------------------------------------------------
    
    思いのほか少ないと思いましたが、ログアウトすると削除されるため、ブラウザ[x]ボタンで閉じた等の理由で画面閉じない限りは基本的に消えてくれるのだと思います。

  • コマンド実行

python2.7 manage.py clearsessions
特にコンソール上は何の応答もなく終了したので、データが消えているか確認します。

python2.7 manage.py dbshell
select count(*) from django_session;
------------------------------------------------
 count 
-------
    1
(1 )
------------------------------------------------

  • スケジューラへの組み込み
    後はこれを日次で実行する設定にしておきます。

落下傘式な覚え方だと、やはり抜け漏れ発生しますね。
普段使いするフレームワークのドキュメントは一度全体をよく読んだほうがいいのかもしれません。
以上です。

コメント