如何在CodeIgniter 3中实现BCRYPT密码哈希算法?
在CodeIgniter 3中实现BCRYPT密码哈希的步骤
1. 调整数据库密码字段长度
BCRYPT哈希后的密码固定为60字符,需将employee表的em_password字段类型修改为VARCHAR(255),预留足够冗余避免截断。
2. 修改密码存储逻辑(注册/重置场景)
所有涉及密码写入数据库的操作,都要先对明文密码生成BCRYPT哈希:
注册场景(调用insertUser前)
在处理注册的控制器代码中添加哈希处理:
// 获取明文密码 $plain_password = $this->input->post('password'); // 生成BCRYPT哈希 $hashed_password = password_hash($plain_password, PASSWORD_BCRYPT); // 替换数据中的明文密码 $data['em_password'] = $hashed_password; // 存入数据库 $this->login_model->insertUser($data);
密码重置场景(更新UpdatePassword方法)
在Login_model.php中自动对重置密码哈希:
public function UpdatePassword($key,$data){ // 若数据包含明文密码,先哈希处理 if(isset($data['password'])){ $data['password'] = password_hash($data['password'], PASSWORD_BCRYPT); } $this->db->where('forgotten_code',$key); $this->db->update('users',$data); }
3. 重构登录验证逻辑
放弃原有的明文密码匹配逻辑,改为先查询用户信息,再验证哈希:
修改Login.php的validate_login方法
function validate_login($email = '', $password = '') { // 仅根据邮箱和状态查询用户,不包含密码 $credential = array('em_email' => $email, 'status' => 'ACTIVE'); $query = $this->login_model->getUserForLogin($credential); if ($query->num_rows() > 0) { $row = $query->row(); // 用PHP原生函数验证密码哈希是否匹配 if(password_verify($password, $row->em_password)){ // 设置登录会话 $this->session->set_userdata('user_login_access', '1'); $this->session->set_userdata('user_login_id', $row->em_id); $this->session->set_userdata('name', $row->first_name); $this->session->set_userdata('email', $row->em_email); $this->session->set_userdata('user_image', $row->em_image); $this->session->set_userdata('user_type', $row->em_role); return 'success'; } } // 验证失败返回false return false; }
模型Login_model.php的getUserForLogin方法无需修改,仅负责查询用户基础信息。
4. 修复“记住密码”的安全漏洞
原代码将明文密码存入Cookie存在严重风险,改为存储加密后的用户标识:
修改Login_Auth中的记住密码逻辑
if ($login_status == 'success') { $row = $this->login_model->getUserForLogin(array('em_email' => $email))->row(); if($remember){ // 加载CI加密库,加密用户ID $this->load->library('encryption'); $encrypted_id = $this->encryption->encrypt($row->em_id); // 存储加密后的用户ID和邮箱到Cookie setcookie('email', $email, time() + (86400 * 30), "/"); setcookie('user_id', $encrypted_id, time() + (86400 * 30), "/"); } else { // 清除Cookie if(isset($_COOKIE['email'])) setcookie('email',' ', time() - 3600, "/"); if(isset($_COOKIE['user_id'])) setcookie('user_id',' ', time() - 3600, "/"); } redirect(base_url() . 'dashboard'); }
添加自动登录逻辑(在index方法中)
public function index() { if ($this->session->userdata('user_login_access') == 1){ redirect(base_url() . 'dashboard'); } // 检查Cookie实现自动登录 if(isset($_COOKIE['email']) && isset($_COOKIE['user_id'])){ $this->load->library('encryption'); try { $user_id = $this->encryption->decrypt($_COOKIE['user_id']); $user = $this->login_model->getUserById($user_id); if($user){ // 设置会话并跳转 $this->session->set_userdata('user_login_access', '1'); $this->session->set_userdata('user_login_id', $user->em_id); $this->session->set_userdata('name', $user->first_name); $this->session->set_userdata('email', $user->em_email); $this->session->set_userdata('user_image', $user->em_image); $this->session->set_userdata('user_type', $user->em_role); redirect(base_url() . 'dashboard'); } } catch(Exception $e){ // 解密失败,清除Cookie setcookie('email',' ', time() - 3600, "/"); setcookie('user_id',' ', time() - 3600, "/"); } } $data=array(); $this->load->view('login'); }
模型新增getUserById方法
在Login_model.php中添加:
public function getUserById($user_id){ return $this->db->get_where('employee', array('em_id' => $user_id))->row(); }
5. 配置CI加密库(可选但推荐)
使用加密库时,需在config.php中设置安全随机密钥:
$config['encryption_key'] = '你的随机安全密钥';
内容的提问来源于stack exchange,提问作者user15136883
相关产品推荐
相关产品推荐

