CodeIgniter 4中验证加密密码时遇到的解密身份验证失败问题
CodeIgniter 4 加密密码验证失败问题
问题重现
数据库记录创建代码
$encrypter = \Config\Services::encrypter(); $password = base64_encode($encrypter->encrypt("12345aA!")); $data = [ "email_address" => "email@gmail.com", "password" => $password, "user_id" => 1 ]; $query = "insert into tblusers(user_id, email_address, password)"; $query = $query . "Values(:user_id,, :email_address, :password)"; $this->db->query($query, $data); $this->db->table("tblusers")->insert($data);
数据库存储密码验证代码
$encrypter = \Config\Services::encrypter(); $model = new UserModel(); $user = $model->where("email_address", "email@gmail.com")->first(); echo $encrypter->decrypt($user["password"]);
尝试直接解密存储的密码仍报错
$encrypted_password = "Py02s1SOIlI/p6sSzqDCqgR81wXuXSSdrA5R8wnLs/SQDig0A2hXjvcn4TfYYaa+Xoq4sMt4gJF5Krec8U8G8fKcrrXsSxbSG3BS"; echo $encrypter->decrypt($encrypted_password);
错误信息
解密失败:验证未通过。
问题原因及解决方案
1. 核心解密逻辑错误
加密时你对encrypter->encrypt()的结果做了base64_encode转换后存入数据库,但解密时直接把数据库中的字符串传给decrypt()方法,缺少对应的base64_decode步骤。encrypter->encrypt()返回的是二进制数据,转成base64字符串存储后,解密必须先转回二进制格式。
修复后的解密代码:
$encrypter = \Config\Services::encrypter(); $model = new UserModel(); $user = $model->where("email_address", "email@gmail.com")->first(); // 先base64解码,再执行解密 echo $encrypter->decrypt(base64_decode($user["password"]));
直接解密存储值的修复代码:
$encrypted_password = "Py02s1SOIlI/p6sSzqDCqgR81wXuXSSdrA5R8wnLs/SQDig0A2hXjvcn4TfYYaa+Xoq4sMt4gJF5Krec8U8G8fKcrrXsSxbSG3BS"; echo $encrypter->decrypt(base64_decode($encrypted_password));
2. 数据库插入代码的额外问题
- SQL语句存在语法错误:
Values(:user_id,, :email_address, :password)中user_id后多了一个逗号,会导致SQL执行失败。 - 代码同时调用了
$this->db->query()和$this->db->table()->insert(),会重复插入两条相同记录,保留其中一种插入方式即可。
修复后的插入代码示例:
$encrypter = \Config\Services::encrypter(); $password = base64_encode($encrypter->encrypt("12345aA!")); $data = [ "email_address" => "email@gmail.com", "password" => $password, "user_id" => 1 ]; // 使用Query Builder方式插入,简洁且安全 $this->db->table("tblusers")->insert($data);
3. 安全建议
不建议用加密存储密码,加密是可逆操作,存在密码泄露风险。正确的密码存储方式应该使用哈希算法,CodeIgniter 4支持原生PHP的哈希验证方法:
// 存储密码时 $hashedPassword = password_hash("12345aA!", PASSWORD_DEFAULT); $data["password"] = $hashedPassword; $this->db->table("tblusers")->insert($data); // 验证密码时 $user = $model->where("email_address", "email@gmail.com")->first(); if (password_verify("用户输入的密码", $user["password"])) { // 密码验证通过 } else { // 密码错误 }
内容的提问来源于stack exchange,提问作者Pankaj
相关产品推荐
相关产品推荐

