CodeIgniter 4 的全局过滤器必须显式注册到 Filters.php 的 $globals 数组中才生效,否则即使类存在、配置正确,请求也不会经过 before() 方法;CI3 无真正全局过滤机制,仅能通过 MY_Controller 或 Hook 变通实现。

CodeIgniter 4 的全局过滤器必须显式注册到 Filters.php 的 $globals 数组里,否则哪怕配置写对、类文件存在,也完全不生效——请求根本不会经过你写的 before() 方法。
CI4 中全局过滤器必须配在 $globals 才生效
很多人把自定义过滤器类写好、在 app/Config/Filters.php 里声明了类名,却忘了最关键的一步:把它加进 $globals['before'] 或 $globals['after']。CI4 不会自动扫描或启用任何过滤器,一切靠手动注册。
-
$globals = ['before' => ['csrf', 'cors', 'auth']]—— 这才是让过滤器真正运行的写法 - 只在
$methods(如'post' => ['csrf'])里配,只会对 POST 路由生效,不是“全局” - 只在路由定义里用
'filter' => 'auth',那只作用于该路由,和全局无关 - 过滤器类必须实现
FilterInterface,且before()方法不能直接exit或die,应返回ResponseInterface或抛出异常
CI3 没有真正意义的“全局过滤器”机制
CodeIgniter 3 没有 Filters.php 和过滤器链概念,所谓“全局过滤”只能靠变通:
- 在
application/core/MY_Controller.php的构造函数里统一调用检查逻辑(比如登录态、IP 黑名单) - 用
hook配置pre_system或post_controller_constructor,但 hook 在 CI3 中默认关闭,需先设$config['enable_hooks'] = TRUE - 无法像 CI4 那样按 HTTP 方法、路由分组精细控制;所有控制器继承 MY_Controller 才能覆盖,漏掉一个就失效
- 注意:CI3 的
$this->input->post(null, TRUE)启用的是 XSS + CSRF 双过滤,但它不是“过滤器”,而是输入读取时的一次性处理
CSRF 过滤器是唯一开箱即用的全局防护,但必须配对启用
CI4 自带 csrf 过滤器,但它不是默认开启的。光在 Security.php 把 $csrfProtection 设为 'cookie',只是准备好了 token 生成逻辑,拦截动作仍依赖过滤器注册。
- 缺一不可的三步:
Security.php设$csrfProtection→Filters.php注册到$globals['before']→ 表单中输出= csrf_field() ?> - 如果只做前两步,POST 请求会直接 403;如果只做后两步,攻击者可伪造无 token 请求绕过验证
- AJAX 场景下,
$csrfRegenerate = true(默认)会导致每次响应都刷新 token,前端必须从响应头(如X-CSRF-TOKEN)或 JSON body 中提取新值,不能缓存初始页的csrf_hash() - CI3 的
$config['csrf_protection'] = TRUE是开关式启用,但同样要配合$this->input->post(null, TRUE)才真正校验,否则形同虚设
自定义过滤器里别直接 echo / print / exit
CI4 的过滤器运行在中间件阶段,响应对象尚未发送。此时用 echo 会污染响应体,exit 会中断整个请求生命周期,导致后续中间件、控制器、视图全部跳过,还可能触发 “headers already sent” 错误。
- 正确做法:在
before()中检测失败时,构造并返回一个ResponseInterface实例,例如return service('response')->setStatusCode(401)->setBody('Unauthorized') - 不要在过滤器里调用
$this->session或$this->db等服务,除非你确认它们已在该阶段初始化(CI4 默认已可用,但自定义服务需检查加载顺序) - 调试时用
log_message('debug', 'filter hit'),而不是var_dump(),避免破坏输出流 - 若需重定向,用
return redirect()->to('/login'),它返回的是ResponseInterface,可被框架正常处理
真正卡住人的从来不是怎么写过滤器类,而是哪一层该配、哪一层必须配、哪一层配了也白配——Filters.php 的 $globals 是 CI4 全局过滤的唯一入口,漏掉它,其他全白搭。


















