Flaskでパスワードを安全に扱う方法!ハッシュ化の仕組みと実装
生徒
「先生、Flaskでログイン機能を作ってるんですが、パスワードってどうやって安全に保存すればいいんですか?」
先生
「とても大事なポイントですね。パスワードは“ハッシュ化”して保存するのが基本です。もし生のパスワードをそのまま保存すると、セキュリティ上の大問題になってしまいます。」
生徒
「ハッシュ化って何ですか?暗号化とは違うんですか?」
先生
「良いところに気がつきました。暗号化は元に戻せますが、ハッシュ化は“元に戻せない”という点が大きな違いなんです。では、詳しく見ていきましょう!」
1. Flaskでパスワードをハッシュ化する理由
パスワードをそのまま(平文といいます)で保存すると、データベースが流出したときに全ユーザーのパスワードが漏れてしまいます。たとえば、次のように保存していると危険です。
users = {
"alice": "password123",
"bob": "123456"
}
これでは、誰かがデータベースをのぞけば一目でパスワードがわかってしまいます。ハッシュ化(Hashing)を使うと、パスワードを一方向の関数で変換し、元の文字列に戻せないようにすることができます。
つまり、たとえデータが漏れても、パスワードそのものは分からないようになります。
2. ハッシュ化とは?暗号化との違いを理解しよう
暗号化は、特殊な「鍵(キー)」を使ってデータを復元できます。しかし、ハッシュ化は「戻せない」仕組みです。例えば、「apple」という文字列をハッシュ化するとこんな感じになります。
apple → 1f3870be274f6c49b3e31a0c6728957f
この結果から元の「apple」を取り出すことはできません。FlaskやPythonでは、werkzeug.securityというライブラリを使って簡単にハッシュ化が行えます。
3. Flaskでパスワードをハッシュ化する実装例
では、Flaskで実際にハッシュ化を行うコードを書いてみましょう。
from flask import Flask, request
from werkzeug.security import generate_password_hash, check_password_hash
app = Flask(__name__)
@app.route('/register', methods=['POST'])
def register():
password = request.form['password']
hashed_pw = generate_password_hash(password)
return f"ハッシュ化されたパスワード: {hashed_pw}"
@app.route('/login', methods=['POST'])
def login():
password = request.form['password']
stored_hash = 'pbkdf2:sha256:260000$abc123$abcdef...' # 仮のハッシュ
if check_password_hash(stored_hash, password):
return "ログイン成功!"
else:
return "パスワードが間違っています。"
generate_password_hash()はパスワードを安全にハッシュ化します。check_password_hash()は、入力されたパスワードと保存されたハッシュを比較して、一致しているか確認します。
4. ハッシュ化の仕組みをもう少し詳しく知ろう
ハッシュ化は、「同じ入力には必ず同じ結果が出る」という特徴があります。しかし、それだけではセキュリティが弱くなります。なぜなら、悪意のある人が「辞書攻撃」という方法で、よく使われるパスワードのハッシュ値を事前に調べてしまうことがあるからです。
そこで登場するのがソルト(Salt)という考え方です。ソルトとは、「ランダムな文字列をパスワードに混ぜてハッシュ化する」仕組みです。これにより、同じパスワードでもハッシュ値が変わり、解析が難しくなります。
例えば:
password123 → ハッシュ化(A1B2C3...)
password123 + ソルト値X9Y7 → ハッシュ化(Z8K4M5...)
Flaskのgenerate_password_hash()関数は、自動でソルトを追加してくれるため、開発者が手動で管理する必要はありません。
5. パスワードを安全に管理するためのベストプラクティス
Flaskアプリを開発する際は、次のルールを守ることでセキュリティを高められます。
- パスワードは必ずハッシュ化して保存する(生の文字列は禁止)
- ソルト付きハッシュを使う(Flaskの関数なら自動で対応)
- HTTPS通信を使って、送信時にパスワードが盗まれないようにする
- ユーザーがパスワードを忘れた場合は、再設定メールを送る(決して元のパスワードを表示しない)
また、セキュリティの専門家は「bcrypt」や「Argon2」といった強力なアルゴリズムを使うことを推奨しています。Flaskのgenerate_password_hash()はこれらにも対応しています。
6. 実際にFlaskで登録とログインを組み合わせる
次のサンプルでは、登録時にパスワードをハッシュ化し、ログイン時にそのハッシュと入力を照合する仕組みを実装しています。
from flask import Flask, request, session, redirect, url_for
from werkzeug.security import generate_password_hash, check_password_hash
app = Flask(__name__)
app.secret_key = "super_secret"
users = {}
@app.route('/register', methods=['POST'])
def register():
username = request.form['username']
password = request.form['password']
users[username] = generate_password_hash(password)
return "登録完了!"
@app.route('/login', methods=['POST'])
def login():
username = request.form['username']
password = request.form['password']
user_hash = users.get(username)
if user_hash and check_password_hash(user_hash, password):
session['user'] = username
return "ログイン成功!"
return "ユーザー名またはパスワードが違います。"
このようにすれば、ハッシュ化されたパスワードしか保存されず、安全なログイン機能を構築できます。
7. ハッシュ化を理解して安全なFlaskアプリを作ろう
Flaskでパスワードを扱うときは、「ハッシュ化」「ソルト」「比較」の3つのポイントを意識すれば、初心者でも安全なWebアプリを作ることができます。
ハッシュ化は単なる技術ではなく、ユーザーの個人情報を守るための大切な仕組みです。どんなに小さなアプリでも、パスワードの安全管理は絶対に軽視してはいけません。