ci4默认session不安全,必须改用redis/database驱动并配置secure/httponly/samesite。filehandler高并发锁阻塞、cookie易被xss窃取、无法跨服务器共享,需显式加固配置并验证生效。

CodeIgniter 4 的 Session 不是开箱即用的“安全会话”,默认 FileHandler 在生产环境必然出问题——高并发下 flock 锁导致接口卡顿、会话丢失,且不设 $secure 和 $httponly 会让 cookie 被 XSS 窃取。必须改驱动、关文件锁、加固 cookie 属性。
为什么 CI4 默认 Session 配置不能直接上线
CI4 启动时自动加载 Session 服务,但默认使用 FileHandler,它依赖系统临时目录 + flock() 文件锁。真实压测中,50+ 并发请求就可能排队等锁,session_start() 阻塞超时,用户看到白屏或 504;更隐蔽的是:同一用户多次刷新,userdata() 返回 NULL 却无报错,因为 session 文件被锁住写失败了。
- 默认
$savePath指向系统/tmp,权限不可控,多应用共用易冲突 - 没配
$secure = true时,HTTPS 站点的 session cookie 仍会被 HTTP 页面读取(混合内容漏洞) -
FileHandler无法跨服务器共享,负载均衡下用户反复登录、状态丢失
必须改用 Redis 或 Database 驱动
Redis 是首选:无锁、毫秒级响应、天然支持过期淘汰。Database 次选,适合已有 MySQL 运维习惯的团队,但要注意索引和表清理。
- 编辑
app/Config/Session.php,把public $driver = 'file';改成public $driver = 'redis'; -
public $savePath = 'tcp://127.0.0.1:6379?database=2&timeout=30';—— 显式指定 DB 编号和超时,避免连接池耗尽 - 若选 Database,需建表:
CREATE TABLE ci_sessions (id VARCHAR(128) NOT NULL PRIMARY KEY, data BLOB NOT NULL, timestamp INT UNSIGNED DEFAULT 0 NOT NULL, ip_address VARCHAR(45) DEFAULT '' NOT NULL, INDEX ci_sessions_timestamp (timestamp));,并在$driver = 'database'后设$table = 'ci_sessions'
Cookie 安全属性三件套缺一不可
Session ID 存在 cookie 里,cookie 不安全,整个会话体系就崩了。这三项必须在 app/Config/Cookie.php 中显式设置:
-
public $secure = true;—— 强制仅 HTTPS 传输,HTTP 请求不带该 cookie -
public $httponly = true;—— JS 无法读取document.cookie,防 XSS 盗用 -
public $samesite = 'Strict';—— 阻断跨站请求携带 cookie,防 CSRF(若需兼容旧浏览器可降为Lax)
漏掉任意一项,攻击者用一个恶意页面就能发起带合法 session cookie 的 POST 请求,完成账户劫持。
验证是否真正生效的两个硬指标
别只看 $this->session->set_userdata('test', 'ok') 能不能写,要验证底层行为是否符合预期:
- 访问任意页面后执行
var_dump(session_status() === PHP_SESSION_ACTIVE);,输出bool(true)才说明 session 已启动 - 在 Redis CLI 中运行
KEYS "ci_session*",应看到键名(如ci_sessionabc123...);若为空,说明$driver或$savePath配置无效,回退到了 file 模式
最常被忽略的是:CI4 的 Session 服务初始化发生在 Filters 执行之后,如果你在自定义 Filter 里提前调用了 $this->session,而该 Filter 又未声明 before 时机,就会触发未初始化错误——务必确认你的 Filter 注册顺序和生命周期阶段。











