CI3表单提交报CSRF verification failed的常见原因:表单缺失有效token或token未被正确识别,涉及配置、手动字段拼写、POST获取方式及session失效等多环节问题。

CI3 表单提交报 CSRF verification failed 的常见原因
直接原因是:表单没带有效 token,或 token 没被框架正确识别。不是配置开了就万事大吉,CI3 的 CSRF 验证链条很短但很脆,漏一环就 403。
config.php 中 csrf_protection 开启但无效
光设 $config['csrf_protection'] = TRUE 不够,还必须同步满足以下条件:
-
$config['csrf_token_name']和$config['csrf_cookie_name']不能和已有 Cookie 冲突(比如多个 CI 应用共用域名时) -
$config['csrf_expire']默认 7200 秒(2 小时),如果用户页面停留超时,token 过期后提交就会失败 -
$config['csrf_regenerate'] = TRUE时,每次请求都会换 token —— 这意味着「打开表单页 → 等待 10 分钟 → 提交」必然失败 - 若用了反向代理或负载均衡,且未透传 Cookie 或修改了
$_SERVER['HTTP_X_FORWARDED_FOR'],CSRF cookie 可能被丢弃
手写表单漏掉或错写 CSRF 字段
CI3 不像 CI4 或 Laravel 那样自动注入,你得手动拼字段,稍错就挂:
- 别写成
<input type="hidden" name="csrf_test_name" value="<?php echo $this->security->get_csrf_hash(); ?>">——name必须是$this->security->get_csrf_token_name()返回的值,不能硬编码 - 别漏掉
value,空字符串或 null 都会导致校验失败 - 如果用了
form_open(),它会自动加字段;但一旦手写表单,就得自己调$this->security->get_csrf_token_name()和$this->security->get_csrf_hash() - 注意:
get_csrf_hash()返回的是当前有效 hash,不是固定值,刷新页面后会变
控制器里没走标准 POST 获取流程
CSRF 校验只在 $this->input->post() 被调用时触发,但前提是它被正确调用:
- 必须用
$this->input->post(null, TRUE)或$this->input->post('field_name', TRUE)—— 第二个参数TRUE启用 XSS + CSRF 过滤,缺了就不校验 - 如果直接读
$_POST,CSRF 校验完全绕过,看似能提交,实则安全形同虚设 - 若用了
$this->input->post()但没传参数,且post()返回空数组(比如表单字段名不匹配),CSRF 校验仍会执行,但因找不到对应 token 字段而失败
最常被忽略的一点:CI3 的 CSRF cookie 是基于 session 的,如果 session 本身失效(比如 session 文件目录不可写、session.gc_maxlifetime 设置太短、或 PHP-FPM 的 session.save_path 权限不对),CSRF token 就无法生成或持久化 —— 此时连表单页都可能拿不到有效 hash。


















