ci4全局过滤器必须显式注册到filters.php的$globals数组才生效,否则请求完全绕过;ci3无真正全局过滤机制,仅能通过my_controller或hook变通实现。

全局过滤器不会自动生效,必须显式注册到 Filters.php 的 $globals 数组中,否则所有请求都绕过它。
CI4 中必须在 Filters.php 里配 $globals
CI4 的过滤器机制是“声明即启用”,光写个类、光改配置都不算数。真正起作用的只有 app/Config/Filters.php 里的 $globals 或 $methods 数组。
-
$globals = ['before' => ['csrf']]表示所有请求(无论路由、方法)在控制器执行前都走csrf过滤器 - 若只配了
$methods = ['post' => ['csrf']],那GET请求完全不校验,PUT/DELETE也不触发 - 自定义过滤器(如
AuthGuard)必须先在$aliases里注册别名,才能在$globals中引用 - 顺序很重要:
['csrf', 'auth']和['auth', 'csrf']执行顺序不同,影响 token 获取与权限判断的依赖关系
CI3 没有全局过滤器概念,靠配置和手动调用
CI3 不支持声明式全局过滤器,所谓“全局”其实是靠配置项 + 控制器内约定行为拼凑出来的。
-
$config['global_xss_filtering'] = TRUE会让$this->input->post()等方法自动调用 XSS 过滤,但它不拦截请求,也不支持自定义逻辑 - CSRF 是开关式启用:
$config['csrf_protection'] = TRUE启用后,框架会在$this->input->post()内部校验 token,但前提是表单已注入隐藏域且未被 JS 覆盖 - 没有中间件或钩子能统一拦截所有请求,想做登录检查?只能每个控制器开头写
if (!$this->session->has_userdata('user_id')) { redirect('login'); } - 试图在
hooks.php里用post_controller_constructor做“伪全局过滤”,容易和缓存、输出压缩冲突,且无法中断请求流程
AJAX 请求下全局过滤器容易失效的三个点
全局过滤器对 AJAX 并不友好,尤其是带 CSRF 的场景,常见报错是 403 或 500,但日志里没线索。
- CI4 默认
$csrfRegenerate = true,每次请求都换 token;前端如果只在页面加载时读一次csrf_token()和csrf_hash(),第二次 AJAX 就必然失败 - 用
form_open()生成的表单会自动塞隐藏域,但 JS 动态提交(如fetch或Uppy)必须手动带headers: { 'X-CSRF-TOKEN': window.csrfToken },且后端要配置允许该 header(Access-Control-Allow-Headers) - API 路由如果被加进
$globals['before'],但返回的是 JSON,csrf过滤器仍会校验——这意味着你得确保每个 API 请求都带合法 token,不能漏掉健康检查、静态资源代理等非业务接口
别把输出过滤当成请求过滤
有人想在全局过滤器里修改响应内容(比如 HTML 压缩、敏感词替换),这在 CI4 中是错的路径。
-
before阶段的过滤器只能访问RequestInterface,拿不到响应体;after阶段能拿到ResponseInterface,但此时视图已渲染完毕,body 是只读流 - 真要改输出,得用中间件(
app/Middleware/HtmlMinify.php),并在app/Config/Middleware.php的$after列表里注册,不是往Filters.php塞 - 误在
before里调用$response->setBody()会直接报Call to undefined method,因为$response此时还是空壳 - 输出过滤和请求过滤的生命周期、对象权限、执行时机完全不同,混用会导致不可预测的空白页或 header 已发送错误
最常被忽略的是:全局过滤器一旦注册,就对所有匹配请求强制执行,包括 favicon.ico、robots.txt、健康检查接口。上线前务必确认哪些路由该放行,用 except 或分组过滤更稳妥。











