CodeIgniter3会话过期后用户无法重新登录问题求助
CodeIgniter3 会话过期后无法重新登录的修复方案
问题根源
会话过期后,users表中存储的session_id未被清理或验证有效性。用户重新登录时,系统检测到数据库中的旧session_id与当前新生成的session_id不一致,误判为账号在其他设备登录。
具体修复步骤
1. 验证存储的session_id是否有效
修改M_Auth模型的get_user_session_id方法,先检查该session_id在ci_sessions表中是否存在且未过期:
public function get_user_session_id($email) { $this->db->where('email', $email); $user = $this->db->get($this->_table)->row(); if (!$user || !$user->session_id) { return NULL; } // 验证session_id是否有效(未过期) $expire_time = time() - $this->config->item('sess_expiration'); $this->db->where('id', $user->session_id); $this->db->where('timestamp >', $expire_time); $valid_session = $this->db->get('ci_sessions')->row(); return $valid_session ? $user->session_id : NULL; }
2. 自动清理过期会话对应的用户session_id
通过CodeIgniter钩子实现会话过期时,自动清空users表中关联的session_id:
配置钩子(application/config/hooks.php)
$hook['post_system'][] = [ 'class' => 'SessionCleanup', 'function' => 'expire_user_sessions', 'filename' => 'SessionCleanup.php', 'filepath' => 'hooks' ];
创建钩子类(application/hooks/SessionCleanup.php)
class SessionCleanup { public function expire_user_sessions() { $CI =& get_instance(); $CI->load->database(); // 获取所有已过期的session记录 $expire_time = time() - $CI->config->item('sess_expiration'); $CI->db->where('timestamp <', $expire_time); $expired_sessions = $CI->db->get('ci_sessions')->result(); if (!empty($expired_sessions)) { $expired_ids = array_column($expired_sessions, 'id'); // 清空对应用户的session_id $CI->db->where_in('session_id', $expired_ids); $CI->db->update('users', ['session_id' => NULL]); } } }
3. 优化登录状态检查逻辑
修改M_Auth模型的check_login_status方法,确保当前会话与用户存储的session_id一致,且会话未过期:
public function check_login_status() { $user_id = $this->session->userdata('user_id'); $current_session_id = session_id(); if (!$user_id) { return FALSE; } $user = $this->db->get_where($this->_table, ['id' => $user_id])->row(); // 会话ID不匹配,直接销毁当前会话 if (!$user || $user->session_id != $current_session_id) { $this->session->sess_destroy(); return FALSE; } // 验证当前会话是否未过期 $expire_time = time() - $this->config->item('sess_expiration'); $this->db->where('id', $current_session_id); $this->db->where('timestamp >', $expire_time); $valid_session = $this->db->get('ci_sessions')->row(); if (!$valid_session) { $this->session->sess_destroy(); $this->db->where('id', $user_id)->update($this->_table, ['session_id' => NULL]); return FALSE; } return TRUE; }
4. 登录时强制覆盖旧session_id
原登录逻辑中已包含更新session_id的代码,只要登录成功,就会将users表中的session_id替换为当前新的session_id,这部分无需额外修改。
内容的提问来源于stack exchange,提问作者Muhammad Ashraf
相关产品推荐
相关产品推荐

