CodeIgniter实现登录失败5次锁定功能的问题排查
修复登录失败次数限制与账户锁定功能
你的代码思路方向是对的,但几个关键细节没处理到位,导致功能出现异常。我帮你梳理问题并给出靠谱的修正方案:
现有代码的核心问题
- 类型比较逻辑错误:你把
$attempts和字符串'5'做比较,如果$attempts是字符串类型(比如直接从POST获取的),字符串的比较规则会导致判断失效——比如'10' <= '5'会被判定为true,因为字符'1'的ASCII码比'5'小。 - 依赖前端传值不安全:直接用
$_POST['attempts']完全不可靠,用户可以篡改这个参数绕过次数限制,必须从数据库读取当前用户的真实失败次数。 - 锁定逻辑不完整:仅输出提示但未真正锁定账户,刷新页面后用户仍能继续尝试登录。
- 缺少成功登录后的重置逻辑:用户登录成功时,没有把失败次数重置为0,会导致后续登录仍受之前的失败次数影响。
修正后的完整实现方案
从你的代码风格看应该是用CodeIgniter框架,我们基于安全可靠的流程重写代码:
1. 先完善数据库表结构
给tb_user添加一个locked字段(tinyint(1)类型,默认值0,0代表未锁定,1代表已锁定),用来标记账户的锁定状态。
2. 登录验证核心代码
// 获取用户输入的用户名和密码 $username = $this->input->post('username'); $password = $this->input->post('password'); // 先查询用户信息,验证是否存在 $user = $this->db->where('username', $username)->get('tb_user')->row(); if (!$user) { echo "用户名不存在!"; return; } // 先检查账户是否已被锁定 if ($user->locked == 1) { echo "你的账户因多次登录失败已被锁定,请联系管理员解锁!"; return; } // 验证密码(假设你的密码是用password_hash加密存储的) if (!password_verify($password, $user->password)) { // 密码错误,处理失败次数 $current_attempts = $user->attempts; if ($current_attempts >= 4) { // 当前已经失败4次,再加1就到5次上限,直接锁定账户 $this->db->where('username', $username); $this->db->set(['locked' => 1, 'attempts' => 5]); $this->db->update('tb_user'); echo "你的账户因5次登录失败已被锁定!"; } else { // 失败次数+1,更新数据库 $this->db->where('username', $username); $this->db->set('attempts', 'attempts + 1', FALSE); $this->db->update('tb_user'); $remaining_times = 5 - ($current_attempts + 1); echo "密码错误!你还有 {$remaining_times} 次尝试机会。"; } } else { // 密码正确,重置失败次数为0 $this->db->where('username', $username); $this->db->set('attempts', 0); $this->db->update('tb_user'); // 这里添加正常登录的逻辑,比如设置session等 echo "登录成功!"; }
额外优化建议
- 添加管理员解锁功能:可以在后台做一个解锁页面,让管理员将用户的
locked字段重置为0,同时把attempts也重置为0。 - 尝试次数自动过期:可以给表加个
last_failed_time字段,记录最后一次登录失败的时间,如果超过1小时(或你设定的时长),自动把attempts重置为0,提升用户体验。 - 替代直接echo:实际项目里建议用CodeIgniter的Flash消息(
$this->session->set_flashdata())来提示用户,比直接echo更符合框架规范。
内容的提问来源于stack exchange,提问作者Mehreen
相关产品推荐
相关产品推荐

