PHP 8.1升级后crypt与password_verify无法验证旧密码求解决
PHP 8.1升级后密码验证失败的解决办法
问题分析
将PHP从7.4升级到8.1后,用户登录时密码验证完全失效:
- 原验证逻辑里
crypt()函数无论输入什么参数,始终返回*0 - 尝试用
password_verify()验证,也一直返回false
问题根源在于旧的密码哈希生成逻辑存在格式缺陷:
- 旧生成函数在盐参数末尾额外添加了
$,但Blowfish算法的合法盐字符仅包含A-Za-z0-9./,这个多余的$破坏了盐的格式规范 - PHP7.4对格式错误的兼容性较强,能忽略这个问题完成验证;但PHP8.1严格遵循算法规范,直接判定无效盐并返回
*0 - 非标准格式的哈希字符串无法被
password_verify()正确解析,导致验证失败
解决方案
方案一:修复crypt()验证逻辑(快速解决)
直接使用数据库中存储的完整哈希值作为crypt()的盐参数,无需手动截取和拼接。crypt()会自动从哈希字符串中提取算法标识、cost值和盐部分,完成正确的密码哈希对比:
// 替换原验证代码 $storedHash = $dbValue; // 从数据库获取的用户哈希 $hashedInput = crypt($password, $storedHash); if ($hashedInput === $storedHash) { // 密码验证成功 }
这个方法无需修改数据库中的旧哈希,直接兼容现有数据,在PHP8.1中可以正常工作。
方案二:逐步迁移到标准哈希格式(长期优化)
为了后续兼容password_verify(),可以在用户验证成功后,使用标准的password_hash()重新生成哈希并更新到数据库,逐步替换旧的非标准哈希:
$storedHash = $dbValue; $hashedInput = crypt($password, $storedHash); if ($hashedInput === $storedHash) { // 验证成功,生成标准哈希 $newHash = password_hash($password, PASSWORD_DEFAULT); // 执行SQL更新数据库中的用户哈希字段 // UPDATE users SET password = ? WHERE id = ? }
后续新注册用户直接使用password_hash()生成哈希,登录时使用password_verify()验证即可:
if (password_verify($password, $storedHash)) { // 密码验证成功 }
内容的提问来源于stack exchange,提问作者Dan B.
相关产品推荐
相关产品推荐

