本日、同僚のエンジニアとハッカソンみたいなことをやってきました。
なかなか盛り上がったのですが、その中で「Flask 標準の session と Flask-Session ってどんな場面で使い分けるの?」をしっかり理解できていないと感じ、いろいろ勉強したのでまとめておきます。
なお、英語だと良記事が多いのですが、英語アレルギーの同僚のために日本語でまとめる、という裏テーマもあります。
標準の session について
早速ハマったのですが、こちら名前だけ見るとセッション管理に関する何かに見えます。(見えますよね・・・?)
しかし、一般的な Web アプリケーションでいうところのセッション管理とは若干意味合いが異なっています。
実際のコードとデータを見てもらうと分かりやすいのですが、
@app.route("/") def top(): session['foo'] = 'foo' return render_template('top.html')
前後は省略しますが、session[key]
に対して何か値を入れてみましょう。
その後、ページにアクセスし、開発者ツールなどでクッキーを見てみましょう。
はい、session
という名前のクッキーが出来ましたね。
この文字列を取り出して見ると、eyJmb28iOiJmb28ifQ.Dc9K2Q.wa2YaXF3ahbq1YmVdDp82y6jhRA
となっています。
これは、base64 でエンコードされた文字列になっています。.
は区切り文字になっており、1つ目に上記で設定した foo
に関するデータが入っています。2つ目以降は値のチェック用です。
では、1つ目の文字列を base64 でデコードしてみましょう。その際、文字列の最後に ==
を付与します。base64 は4文字ずつ変換する仕様で、文字列の長さを4の倍数にするために、足りない部分を =
で埋める必要があります。
import base64 base64.urlsafe_b64decode('eyJmb28iOiJmb28ifQ==') #=> b'{"foo":"foo"}'
はい、設定した foo
に関するデータが、そのまま出てきましたね。
ちなみに、上記は b'{"foo":"foo"}'
と短いためこのような仕様ですが、これがある一定の長さを上回ると仕様が変わり、zlib での圧縮が追加されます。↓の部分で分岐します。
https://github.com/pallets/itsdangerous/blob/master/itsdangerous.py#L878
実際にやってみましょう。
@app.route("/") def top(): session['foo'] = 'foo' * 20 return render_template('top.html')
そして、ページにアクセスし、クッキーを取得します。今回は、.eJyrVkrLz1eyApFkI6VaANY3HE8.Dc9QcQ.6WhEXofYJc2H-uOUvMeTeXnLL5s
になりました。先頭に .
が付与されていれば OK です。
import base64 import zlib zlib.decompress(base64.urlsafe_b64decode('eJyrVkrLz1eyApFkI6VaANY3HE8=')) #=> b'{"foo":"foofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoofoo"}'
はい、無事にデータを取得できましたね。
以上のことから、標準の session はクッキーに全ての値を入れているだけであることが分かります。
Flask-Session について
詳しい導入方法は公式サイトを見て頂くとして、今回は sqlalchemy
で動作させたいと思います。PostgreSQL を使います。
設定を終え、ブラウザのクッキーをクリアした後にページにアクセスすると、以下の通り名前は session
と同じですが、文字列の雰囲気が変わったことに気付きます。
では、セッションテーブルの様子も見てみましょう。デフォルトでは、sessions
というテーブル名です。
まず、テーブル定義ですが、以下の通りです。
次に、レコードですが、以下の通りです。data
がバイナリデータのため長すぎて切れていますが、雰囲気は感じ取って頂けるかと思います。
以上のことから、Flask-Session は一般的な Web アプリケーションでいうところのセッション管理の役割を果たすものであることが分かります。
おわりに
というわけで、かなりざっくりな感じになってしまいましたが、Flask 標準の session と Flask-Session の違いをまとめてみました。
私自身まだ理解し切れていない部分も多いため、「ここ違うよ!」といった箇所がありましたら、ご指摘頂けますと有り難いです。