CodeIgniter从CyberSource支付网关重定向后会话丢失求解决方案
解决CodeIgniter 3.x + CyberSource回调时会话丢失问题
核心原因
CyberSource回调属于跨站请求,Chrome等现代浏览器默认对SameSite=Lax的Cookie有跨站传递限制,而CodeIgniter 3.x原生不支持配置SameSite属性,直接在cookie_path里拼接;SameSite=None会因CI内部Cookie处理逻辑问题不生效,导致回调时会话Cookie无法被携带,进而丢失登录状态。
正确解决方案
1. 修复Session Cookie的SameSite配置(推荐,不破坏系统文件的方式)
由于CI3原生不支持SameSite,需要手动修改Session驱动的Cookie设置逻辑,推荐自定义Session驱动:
方法:自定义Session Cookie驱动
- 在
application/libraries/Session/drivers目录下创建MY_Session_cookie_driver.php(如果使用数据库会话驱动,则对应创建MY_Session_database_driver.php),内容如下:
<?php defined('BASEPATH') OR exit('No direct script access allowed'); class MY_Session_cookie_driver extends CI_Session_cookie_driver { protected function _set_cookie($session_id) { if (is_null($session_id)) { return $this->_destroy(); } $expire = ($this->_config['sess_expiration'] === 0) ? 0 : time() + $this->_config['sess_expiration']; // 用PHP7.3+支持的数组方式设置Cookie参数,添加SameSite=None $cookie_options = [ 'expires' => $expire, 'path' => $this->_config['cookie_path'], 'domain' => $this->_config['cookie_domain'], 'secure' => $this->_config['cookie_secure'], 'httponly' => $this->_config['cookie_httponly'], 'samesite' => 'None' ]; return setcookie($this->_config['cookie_name'], $session_id, $cookie_options); } }
- 确保
config.php里的Cookie配置正确:
$config['cookie_secure'] = TRUE; // HTTPS环境必须设为TRUE,SameSite=None要求搭配Secure属性 $config['cookie_domain'] = '.yourdomain.com'; // 根域名格式,确保跨子域名可用(按需设置) $config['cookie_path'] = '/'; $config['cookie_httponly'] = TRUE; $config['sess_expiration'] = 7200; // 会话过期时间设为2小时,覆盖支付流程时长
2. 恢复错误的Session配置
之前修改system/libraries/Session/session.php中session.name为session.id的操作逻辑错误,会导致会话ID混乱,必须改回原代码:
ini_set('session.name', $params['cookie_name']);
3. 排除其他干扰项
- CSRF验证拦截:如果开启了CI的CSRF验证,必须将CyberSource的回调URI加入白名单:
$config['csrf_exclude_uris'] = ['payments/cybersource_callback']; // 替换为你的实际回调URI - 会话存储权限:如果使用文件会话,确保
application/sessions目录权限为700,且归属Web服务器用户;如果使用数据库会话,检查会话表是否正常存储数据,未被提前清理。
验证步骤
- 登录应用后,打开浏览器开发者工具(F12)→ Application → Cookies,查看会话Cookie的
SameSite属性是否为None,Secure是否为true。 - 发起支付并触发回调,在回调控制器的方法开头添加调试代码:
var_dump($this->session->userdata('user_id')); // 打印用户ID,确认是否存在 var_dump(session_id()); // 打印会话ID,对比登录时的ID是否一致
内容的提问来源于stack exchange,提问作者Nishant Solanki
相关产品推荐
相关产品推荐

