はじめに
Webアプリを作るとき、避けて通れないのが「ログイン機能」です。
ユーザー認証の仕組みは最初はややこしく感じますが、分解して考えると意外とシンプルです。
今回は、自分の理解を整理しつつ、ログインの流れやセッション管理についてまとめてみました。
書こうと思ったきっかけ
最近、ログイン機能を実装する機会があり、「結局どんな仕組みで動いているのか?」と疑問に思ったのがきっかけです。
特に、セッション管理やJWTの違いについて調べる中で、整理しておきたいと感じました。
同じように悩んでいる方にも参考になれば嬉しいです。
ユーザー認証の流れ
ユーザーがログインフォームに情報を入力
- ユーザー名(またはメールアドレス)とパスワードを入力し、「ログイン」ボタンを押す。
サーバーが入力情報を検証
- フォームから送信された情報をサーバーが受け取り、データベース内のユーザー情報と照合する。
- パスワードは通常、ハッシュ化(暗号化)されて保存されているため、ユーザーが入力したパスワードも同じ方法でハッシュ化し、一致するか確認する。
認証成功 or 失敗
- 成功:セッションやトークンを発行し、ログイン成功を通知。
- 失敗:エラーメッセージを表示し、再試行を促す。
セッション管理の方法
ログイン後、ユーザーの状態を維持するために、以下のいずれかの方法でセッション管理を行う。
セッションID(クッキー方式)
仕組み:
- 認証成功後、サーバーは一意の「セッションID」を発行。
- クライアントのブラウザに「クッキー」として保存。
- 次回リクエスト時にセッションIDを送信し、サーバー側でユーザー情報を参照する。
特徴:
- 一般的なログイン方法
- セッション情報はサーバー側で管理
JSON Web Token(JWT)
仕組み:
- 認証成功後、サーバーは「JWTトークン」を発行。
- トークンをブラウザの
localStorage
またはsessionStorage
に保存。 - 以降のリクエスト時にトークンをヘッダーに含める。
特徴:
- サーバーがセッションを管理しなくてよい(スケールしやすい)
- トークンが改ざんされにくい(秘密鍵で署名)
ログイン時のセキュリティ対策
パスワードのハッシュ化
- パスワードは平文で保存せず、
bcrypt
やargon2
などでハッシュ化する。
ブルートフォース攻撃対策
- 短時間で何度もログイン失敗するとアカウントをロックする。
CSRF対策(クロスサイトリクエストフォージェリ対策)
- CSRFトークンを使い、他サイトから不正リクエストが送られないようにする。
XSS対策(クロスサイトスクリプティング対策)
- JavaScript の
document.cookie
を使えないように、HttpOnly
属性をつける。
ログアウトの仕組み
セッション方式の場合
- サーバー側のセッション情報を削除し、クライアント側のクッキーも無効化する。
JWT方式の場合
- クライアント側の
localStorage
やsessionStorage
からトークンを削除する。 - トークンの有効期限 (
exp
) を短めに設定しておく。
実装の簡単な例(Flask)
from flask import Flask, request, jsonify, session
from werkzeug.security import generate_password_hash, check_password_hash
app = Flask(__name__)
app.secret_key = "secret"
# 仮のデータベース
users = {
"honda": generate_password_hash("password123")
}
@app.route("/login", methods=["POST"])
def login():
data = request.json
username = data.get("username")
password = data.get("password")
if username in users and check_password_hash(users[username], password):
session["user"] = username # セッションにユーザーを保存
return jsonify({"message": "ログイン成功"}), 200
else:
return jsonify({"message": "ログイン失敗"}), 401
@app.route("/logout", methods=["POST"])
def logout():
session.pop("user", None) # セッションを削除
return jsonify({"message": "ログアウトしました"}), 200
if __name__ == "__main__":
app.run(debug=True)
- ユーザー認証(パスワードのハッシュ化・照合)
- セッション管理(ログイン・ログアウト)
- API エンドポイント(
/login
・/logout
)
簡単なログイン機能としては十分ですが、実運用では データベース管理・セキュリティ対策(JWT、CSRF 対策など) を追加するのが一般的です!
まとめ
ログイン機能は、「ユーザーを確認し、その状態を維持する」仕組みです。
セッションID(クッキー)方式やJWT方式、それぞれにメリット・デメリットがあり、状況に応じた選択が必要です。
また、セキュリティ対策も重要で、パスワードのハッシュ化やCSRF対策などを意識することが求められます。
自分もまだ勉強中ですが、こうして整理することで理解が深まったように思います。