如何实现原生PHP站点与CodeIgniter3站点跨站自动登录
原生PHP站与CodeIgniter 3站跨站登录状态互通实现方案
核心逻辑采用带签名的时效临时令牌做免密校验,无需共享Session、无需修改原有登录流程,兼顾安全性和兼容性。
绝对不要直接在跳转链接里明文传输账号密码,也不要不加签名校验直接传用户ID,会造成任意账号登录的严重安全漏洞
第一步:提前约定双方校验规则
两个站点提前配置一个完全一致的共享密钥,建议用32位以上随机字符串(比如f7a9d2s4g6h8j0k1l3m5q7w9e2r4t6y8u0i),密钥禁止外泄,只存在两个站点的服务端代码里。
第二步:改造主站aside.php的跳转逻辑
替换原有的ACADEMY导航块代码,增加登录态判断:用户已登录时生成带签名的免密跳转链接,未登录时仍跳转到普通登录页。
<?php // 配置和CI3站完全一致的共享密钥 $shared_secret = '替换成你自己生成的32位以上随机密钥'; $jump_url = 'https://localhost/academy_lms/login'; // 主站已登录状态下生成免密令牌,这里根据你主站实际存的session字段调整,假设登录用户ID存在$_SESSION['user_id'],对应CI3站的AgentID if (isset($_SESSION['user_id']) && !empty($_SESSION['user_id'])) { $agent_id = $_SESSION['user_id']; $expire_time = time() + 300; // 令牌5分钟后过期,避免被截获后长期可用 // 生成防篡改签名 $sign = hash_hmac('sha256', $agent_id . '|' . $expire_time, $shared_secret); // 拼接免密登录地址 $jump_url = 'https://localhost/academy_lms/login/sso_login?' . http_build_query([ 'agent_id' => $agent_id, 'expire' => $expire_time, 'sign' => $sign ]); } ?> <li class="nav-item"> <a href="<?php echo $jump_url; ?>" target="_blank" class="nav-link <?php if($pageid==19){ echo 'active';}?>"> <i class="nav-icon"><i class="fa fa-book"></i></i> <p> ACADEMY </p> </a> </li>
第三步:CI3站新增SSO免密登录接口
不要修改原有登录表单、validate_login校验逻辑,在Login控制器中新增sso_login方法专门处理跨站免密请求,不影响原有普通登录流程。
打开CI3站的application/controllers/Login.php,添加以下方法:
public function sso_login() { // 配置和主站完全一致的共享密钥 $shared_secret = '和主站填的一模一样的随机密钥'; // 获取请求参数 $agent_id = $this->input->get('agent_id', true); $expire = intval($this->input->get('expire', true)); $sign = $this->input->get('sign', true); // 参数缺失、令牌过期直接跳普通登录页 if (empty($agent_id) || empty($expire) || empty($sign) || $expire < time()) { redirect('login'); return; } // 校验签名合法性,防止参数被篡改 $check_sign = hash_hmac('sha256', $agent_id . '|' . $expire, $shared_secret); if (!hash_equals($check_sign, $sign)) { redirect('login'); return; } // 校验通过,查询对应用户是否存在,这里替换成你自己项目的用户模型、查询方法 $this->load->model('user_model'); $user = $this->user_model->get_by_agentid($agent_id); if (!$user) { redirect('login'); return; } // 以下代码直接复制你原有validate_login方法中,登录成功后写入session的逻辑即可 $this->session->set_userdata('login_status', true); $this->session->set_userdata('user_id', $user->id); $this->session->set_userdata('agent_id', $user->AgentID); // 其他原有登录需要写入的session字段、登录日志记录逻辑都照搬 // 登录成功后跳转到站点内部页面,根据你的需求调整地址 redirect('home'); }
配置注意事项
- 如果CI3站开启了CSRF防护,需要把
login/sso_login加入CSRF白名单,配置路径是application/config/config.php,找到$config['csrf_exclude_uris']数组添加上该路径即可。 - sso_login接口不需要经过reCAPTCHA校验,因为请求来自主站的可信跳转,不会被恶意刷接口。
- 两个站点如果部署在正式环境,必须用HTTPS协议,避免令牌在传输过程中被截获。
- 令牌有效期不要设置过长,5分钟足够覆盖用户点击链接到页面加载完成的时长,过期自动失效。
内容的提问来源于stack exchange,提问作者Erica Mae Obando
相关产品推荐
相关产品推荐

