PHPでログイン機能を作るとき、パスワードをそのままDBへ保存してはいけません。漏えい時の被害を抑えるため、password_hash() でハッシュ化し、ログイン時は password_verify() で照合します。
この記事では、登録時の保存、ログイン時の照合、将来の再ハッシュまでを最小構成で整理します。
登録時の保存
<?php
$password = $_POST['password'] ?? '';
if (strlen($password) < 12) {
throw new RuntimeException('パスワードは12文字以上にしてください。');
}
$hash = password_hash($password, PASSWORD_DEFAULT);
// 例: DBには平文ではなく $hash を保存する
$stmt = $pdo->prepare(
'INSERT INTO users (email, password_hash) VALUES (:email, :password_hash)'
);
$stmt->execute([
':email' => $_POST['email'],
':password_hash' => $hash,
]);
ログイン時の照合
<?php
$stmt = $pdo->prepare(
'SELECT id, email, password_hash FROM users WHERE email = :email LIMIT 1'
);
$stmt->execute([
':email' => $_POST['email'] ?? '',
]);
$user = $stmt->fetch();
if (!$user || !password_verify($_POST['password'] ?? '', $user['password_hash'])) {
throw new RuntimeException('メールアドレスまたはパスワードが正しくありません。');
}
if (password_needs_rehash($user['password_hash'], PASSWORD_DEFAULT)) {
$newHash = password_hash($_POST['password'], PASSWORD_DEFAULT);
$update = $pdo->prepare(
'UPDATE users SET password_hash = :password_hash WHERE id = :id'
);
$update->execute([
':password_hash' => $newHash,
':id' => $user['id'],
]);
}
実装のポイント
| 関数 | 役割 |
|---|---|
password_hash() | パスワードを安全な形式のハッシュに変換する |
password_verify() | 入力されたパスワードと保存済みハッシュを照合する |
password_needs_rehash() | 推奨アルゴリズムやコスト変更時に再ハッシュが必要か判断する |
PASSWORD_DEFAULT | PHPが推奨する既定アルゴリズムを使う |
やってはいけないこと
- パスワードを平文で保存する
md5()やsha1()だけで保存する- ログイン失敗理由を細かく出しすぎる
- DBエラーや例外にパスワードを含める