You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用password_verify()验证哈希密码时如何引用数据库存储的哈希值

问题说明

当前登录校验逻辑无法正常工作的核心原因:

  • password_verify()第二个参数被硬编码为固定字符串d8578edf8458ce06fbc5bb76a58c5ca4,没有读取数据库查询到的当前用户对应的密码哈希值
  • 这个32位字符串是MD5算法生成的哈希,和password_hash($string, PASSWORD_DEFAULT)生成的60位以上标准哈希格式完全不兼容,直接传入password_verify()会永远返回校验失败
  • 现有SQL语句直接拼接用户传入的手机号/邮箱参数,存在SQL注入风险
正确实现代码

首先确认数据库用户表存储密码哈希的字段(示例用user_password作为字段名,字段类型需设置为varchar(255)保证能存下完整哈希),修改后的代码如下:

public function hashPassword($string){
   return password_hash($string, PASSWORD_DEFAULT);
}

public function login($phonenumber, $password){
   // 改用参数绑定查询,避免SQL注入
   $users = DB::select("SELECT * FROM $this->tableName WHERE 
   (user_phonenumber = ? OR user_email=?) 
   AND user_state !='blocked'", [$phonenumber, $phonenumber]);

   if (count($users)>0){
        $user = $users[0];
        // 引用查询结果中当前用户的密码哈希字段做校验
        if(password_verify($password, $user->user_password)) 
        {
            @session_start();
            $subscriptionModel = new SubscriptionModel();
            $isRegistered = $subscriptionModel->isSubscribed($user->user_id);
            $userToSession = $user;
            $userToSession->isRegistered = $isRegistered;
            $_SESSION["user"] = $userToSession;
            return $user;
        }
   }
   return false;
}

注意:后续新用户注册、用户修改密码的逻辑,必须统一调用hashPassword()方法生成密码哈希后存入数据库,禁止存储明文、MD5等不安全的哈希值。

历史MD5哈希兼容方案

如果你数据库里现存的密码都是类似示例里的32位MD5哈希(也就是之前注册逻辑没有调用hashPassword()方法生成哈希),不能直接用上面的代码校验,需要做平滑迁移:

  1. 校验时先判断当前存储的哈希是不是MD5格式(长度32位、全十六进制字符)
  2. MD5格式的哈希先用md5($password)和存储值做比对
  3. 比对成功后,调用hashPassword()给当前用户生成新的标准password哈希,更新到数据库对应字段,后续就可以直接用password_verify()校验

兼容校验段示例代码:

// 替换原来的password_verify判断逻辑
$verifyPass = false;
if (strlen($user->user_password) == 32 && ctype_xdigit($user->user_password)) {
    // 兼容旧MD5哈希校验
    if (md5($password) === $user->user_password) {
        $verifyPass = true;
        // 校验通过后更新为标准哈希,完成迁移
        $newHash = $this->hashPassword($password);
        DB::update("UPDATE $this->tableName SET user_password = ? WHERE user_id = ?", [$newHash, $user->user_id]);
    }
} else {
    // 标准password哈希正常校验
    $verifyPass = password_verify($password, $user->user_password);
}

if ($verifyPass) {
    // 写入session、返回用户信息等原有登录成功逻辑
}

内容的提问来源于stack exchange,提问作者little oghara

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 23:24:24