本文目录导读:

在PHP项目中,处理密码哈希与验证时,永远不要使用 MD5、SHA1 或简单的 base64_encode,PHP 提供了专门用于密码哈希的 API,既安全又易于使用。
以下是 PHP 项目密码哈希与验证的标准实践:
核心 API:password_hash 和 password_verify
这是 PHP 5.5+ 内置的密码处理标准库。
注册/创建用户时:哈希密码
<?php
// 用户提交的密码(例如来自表单)
$userPassword = $_POST['password'];
// 使用 bcrypt 算法进行哈希(默认成本系数为 10)
$hashedPassword = password_hash($userPassword, PASSWORD_DEFAULT);
// 或者指定使用 bcrypt 并自定义成本(推荐)
$options = [
'cost' => 12, // 成本系数,范围 4-31,越大越安全但越慢
];
$hashedPassword = password_hash($userPassword, PASSWORD_BCRYPT, $options);
// 将 $hashedPassword 存入数据库
// INSERT INTO users (username, password) VALUES ('admin', '$hashedPassword');
?>
重要说明:
PASSWORD_DEFAULT:使用当前 PHP 版本推荐的算法(目前是bcrypt,未来可能会更新为更好的算法)。PASSWORD_BCRYPT:明确指定使用bcrypt算法,生成的哈希长度固定为 60 个字符。- 不要手动加盐:
password_hash会自动生成一个足够安全的随机盐,并将盐包含在哈希结果中。
登录时:验证密码
<?php
// 用户输入的密码
$userInputPassword = $_POST['password'];
// 从数据库中获取该用户的哈希密码(假设 $userFromDB 是从数据库查询的结果)
$storedHash = $userFromDB['password']; // "$2y$10$..."
// 验证密码
if (password_verify($userInputPassword, $storedHash)) {
// 密码正确!创建会话或发放 Token
$_SESSION['user_id'] = $userFromDB['id'];
echo "登录成功!";
} else {
// 密码错误
echo "密码错误!";
}
?>
进阶:密码是否需要重新哈希(Hash Upgrading)
当服务器性能提升或 PHP 版本更新(推荐算法变化)时,你可能需要提高 cost 值,此功能可以无缝升级密码哈希。
<?php
// 在用户登录成功后(确认密码正确时)
if (password_verify($userInputPassword, $storedHash)) {
// 检查是否需要重新哈希(例如成本系数变化或算法更新)
if (password_needs_rehash($storedHash, PASSWORD_DEFAULT, ['cost' => 12])) {
// 使用当前参数重新哈希密码
$newHash = password_hash($userInputPassword, PASSWORD_DEFAULT, ['cost' => 12]);
// 更新数据库中的哈希值
// UPDATE users SET password = '$newHash' WHERE id = $userId;
}
// 登录逻辑...
}
?>
数据库字段设计
建议存储密码哈希值的字段类型为:
- 类型:
VARCHAR(255)或CHAR(60)(如果固定使用 bcrypt)。 - 长度:至少设置 255 字符,以兼容未来可能更新的算法(如 Argon2 产生的哈希更长)。
安全性建议
- 永远不要限制密码长度:很多用户使用密码管理器生成长密码,只限制最短长度(如 8 位),不限制最大长度(或者设一个很高的上限,如 1000)。
- 永远不要明文存储密码:这是最基础的底线。
- 使用 HTTPS:在传输密码时必须使用 HTTPS,防止中间人攻击。
- 不要在日志中记录密码:即使是错误的密码。
- 使用 Argon2id(PHP 7.2+):如果有条件,可以指定 Argon2id 算法(
PASSWORD_ARGON2ID),它比 bcrypt 更安全(抵抗 GPU 和侧信道攻击更好)。$hashedPassword = password_hash($password, PASSWORD_ARGON2ID, [ 'memory_cost' => 1<<17, // 128MB 'time_cost' => 4, 'threads' => 2, ]);
完整示例(面向对象风格)
class PasswordManager {
public static function hash(string $plainPassword): string {
return password_hash($plainPassword, PASSWORD_DEFAULT, [
'cost' => 12
]);
}
public static function verify(string $plainPassword, string $storedHash): bool {
return password_verify($plainPassword, $storedHash);
}
public static function needsRehash(string $storedHash): bool {
return password_needs_rehash($storedHash, PASSWORD_DEFAULT, [
'cost' => 12
]);
}
}
// 使用
$hash = PasswordManager::hash('mySecretPassword123');
if (PasswordManager::verify('mySecretPassword123', $hash)) {
echo "匹配成功!";
}
| 操作 | 应使用的函数 | 不要使用 |
|---|---|---|
| 哈希密码 | password_hash() |
md5(), sha1(), hash() 无 salt |
| 验证密码 | password_verify() |
直接比较 |
| 检查是否需要重哈希 | password_needs_rehash() |
手动判断算法 |
| 存储 | VARCHAR(255) |
CHAR(32) 或 TEXT |
这是 PHP 官方推荐、最安全且最简单的密码处理方式。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播