より良いトークンの生成

flask-app プロジェクトの内の utils.py を開きます:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import json
import base64
from datetime import datetime

def generate_session(username):
    ### Generate sessionId
    session_obj = {"username": username, "timestamp": datetime.now().isoformat()}
    session_id = base64.b64encode(json.dumps(session_obj).encode("utf-8"))
    return session_id

def parse_session(session_obj):
    ### Parse sessionId
    session_obj = json.loads(base64.b64decode(session_obj).decode("utf-8"))
    return session_obj

sessionId を生成するために使用される generate_session 関数があります。sessionId は、username フィールドと timestamp フィールドを含む base64 エンコードされた JSON オブジェクトであるため、非常に予測しやすい方法で生成されます。Salt を追加するだけで認証情報の不備を防ぐことができます。簡易な修正のために、secrets を使用して、セッションオブジェクトにランダムな値をいくつか設定します。secrets モジュールは、パスワードとセキュリティトークンの管理に適した、暗号学的に強力な乱数を提供します。

他のプログラミング言語については、この Guideをチェックして、その言語で使える セキュア乱数ジェネレータ を知ることができます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
import secrets
import json
import base64
from datetime import datetime

def generate_session(username):
    ### Generate sessionID
    session_obj = {"username": username, "timestamp": datetime.now().isoformat(), "salt": secrets.token_urlsafe()}
    session_id = base64.b64encode(json.dumps(session_obj).encode("utf-8"))
    return session_id

def parse_session(session_obj):
    ### Parse sessionId
    session_obj = json.loads(base64.b64decode(session_obj).decode("utf-8"))
    return session_obj

上記により sessionId を予測しにくくするはずです。しかしこれは Broken Authentication の問題を完全には解決できません。認証されたユーザー(発行されたトークンがメモリまたはデータベースに保存されている場所)のすべてのリクエストに対して Salt を検証する必要があるためです。完全な解決のためには、自分で実装するか、Flask-Login の使用、またはAmazon Cognito などのアイデンティティサービスを使用する方法があります。

token_urlsafe () 関数は、ランダムで URL セーフなテキスト文字列を生成します。デフォルトでは、32 バイト 相当のランダムな文字列が生成されます。少なくとも 2015 年までは、現在の計算能力から保護するには32バイトで十分であると考えられています。文字列のサイズは自分で指定することも、デフォルトのままにしておくこともできます(時間の経過とともに要件は変化します)