本文目录导读:

在 PHP 中,处理密码哈希的正确方式是使用 PHP 内置的 password_hash() 和 password_verify() 函数。永远不要使用 md5()、sha1() 或自己编写的加密算法来存储密码。
以下是标准且安全的做法:
注册时:创建密码哈希
使用 password_hash() 函数,它会自动选择一个强哈希算法(目前默认是 bcrypt),并包含一个随机的盐值(salt)。
<?php // 用户提交的原始密码 $password = 'my_secure_password'; // 创建哈希值 $hash = password_hash($password, PASSWORD_DEFAULT); // $hash 看起来像这样(随机盐值,长度固定): // $2y$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy // 将 $hash 存入数据库(varchar(255) 足够) ?>
关键点:
PASSWORD_DEFAULT:使用当前 PHP 版本推荐的算法(目前是 bcrypt),PHP 更新后可能会改用更强的算法,但现有哈希值依然可以验证。- 不需要手动加盐:函数自动包含。
- 输出长度固定为 60 个字符(bcrypt)或 255(未来算法),数据库字段建议设为
VARCHAR(255)。
登录时:验证密码
使用 password_verify() 函数验证用户输入的密码与数据库中的哈希值是否匹配。
<?php
// 用户输入的密码(例如从表单获取)
$userInputPassword = 'my_secure_password';
// 从数据库取出的哈希值
$storedHash = '$2y$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy';
// 验证
if (password_verify($userInputPassword, $storedHash)) {
echo "登录成功!";
} else {
echo "密码错误!";
}
?>
密码需要重新哈希(可选但推荐)
password_needs_rehash() 检测到当前哈希使用的算法比默认算法旧,建议重新哈希密码(例如在用户登录时)。
<?php
if (password_verify($password, $storedHash)) {
// 检查是否需要更新哈希
if (password_needs_rehash($storedHash, PASSWORD_DEFAULT)) {
// 生成新哈希并更新数据库
$newHash = password_hash($password, PASSWORD_DEFAULT);
// 更新数据库中的密码字段为 $newHash
}
// 登录成功...
}
?>
调整 bcrypt 的工作因子(成本)
如果需要提高安全性(例如应对算力增长),可以指定 cost 参数,成本越高,哈希计算越慢,抵御暴力破解的能力越强。
<?php
$options = [
'cost' => 12, // 默认是 10,范围 4-31
];
$hash = password_hash($password, PASSWORD_BCRYPT, $options);
?>
注意:成本每增加 1,计算时间大约翻倍,测试你的服务器能接受的最大成本(10-12 较合适)。
完整示例:注册与登录
注册(register.php)
<?php
$password = $_POST['password'];
$hash = password_hash($password, PASSWORD_DEFAULT);
// 存入数据库(伪代码)
// $db->query("INSERT INTO users (username, password) VALUES (?, ?)", [$username, $hash]);
?>
登录(login.php)
<?php
$username = $_POST['username'];
$password = $_POST['password'];
// 从数据库获取用户数据
// $user = $db->query("SELECT * FROM users WHERE username = ?", [$username]);
if ($user && password_verify($password, $user['password'])) {
// 登录成功,设置 session
session_start();
$_SESSION['user_id'] = $user['id'];
header('Location: dashboard.php');
} else {
echo "用户名或密码错误";
}
?>
为什么不用 md5/sha1?
| 方法 | 安全性 | 说明 |
|---|---|---|
md5($pass) |
❌ 极低 | 彩虹表可秒破,无盐值 |
sha1($pass) |
❌ 低 | 计算极快,暴力破解简单 |
password_hash() |
✅ 强 | 内置盐值、自适应算法、未来兼容 |
- 创建哈希:
$hash = password_hash($password, PASSWORD_DEFAULT); - 验证密码:
password_verify($password, $hash) - 无需手动处理盐值,无需担心算法细节。
PHP 的密码哈希 API 是经过安全专家设计的,直接使用即可获得强安全保障。