モブプロな人たちのブログ

Web サービス開発しているエンジニアの日記です。Python 大好き Flask 大好き。たまに Swift で iOS ゲーム開発も。

Flask(Python) 標準の session と Flask-Session の違い

本日、同僚のエンジニアとハッカソンみたいなことをやってきました。

なかなか盛り上がったのですが、その中で「Flask 標準の session と Flask-Session ってどんな場面で使い分けるの?」をしっかり理解できていないと感じ、いろいろ勉強したのでまとめておきます。

なお、英語だと良記事が多いのですが、英語アレルギーの同僚のために日本語でまとめる、という裏テーマもあります。

f:id:kaorr_mob:20180101080410p:plain

標準の session について

早速ハマったのですが、こちら名前だけ見るとセッション管理に関する何かに見えます。(見えますよね・・・?)

しかし、一般的な Web アプリケーションでいうところのセッション管理とは若干意味合いが異なっています。

実際のコードとデータを見てもらうと分かりやすいのですが、

@app.route("/")
def top():
    session['foo'] = 'foo'
    return render_template('top.html')

前後は省略しますが、session[key] に対して何か値を入れてみましょう。

その後、ページにアクセスし、開発者ツールなどでクッキーを見てみましょう。

f:id:kaorr_mob:20180505230447p:plain

はい、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 と同じですが、文字列の雰囲気が変わったことに気付きます。

f:id:kaorr_mob:20180505233824p:plain

では、セッションテーブルの様子も見てみましょう。デフォルトでは、sessions というテーブル名です。

まず、テーブル定義ですが、以下の通りです。

f:id:kaorr_mob:20180505234346p:plain

次に、レコードですが、以下の通りです。data がバイナリデータのため長すぎて切れていますが、雰囲気は感じ取って頂けるかと思います。

f:id:kaorr_mob:20180505234909p:plain

以上のことから、Flask-Session は一般的な Web アプリケーションでいうところのセッション管理の役割を果たすものであることが分かります。

おわりに

というわけで、かなりざっくりな感じになってしまいましたが、Flask 標準の session と Flask-Session の違いをまとめてみました。

私自身まだ理解し切れていない部分も多いため、「ここ違うよ!」といった箇所がありましたら、ご指摘頂けますと有り難いです。