Beego过滤器需按阶段选择挂载点:BeforeRouter适合全局重定向和WAF拦截但无session;BeforeExec适合权限校验但不处理静态资源;静态资源必须用BeforeStatic并手动管理session。

Beego 的过滤器不是“写完注册就能用”,关键得看它挂在哪一环——BeforeRouter 拦不住静态文件,BeforeExec 拿不到未初始化的 session,错一个位置,整个权限逻辑就失效。
过滤器该挂 BeforeRouter 还是 BeforeExec?
取决于你要干预的阶段:
-
BeforeRouter:路由还没开始匹配,适合做全局重定向(如未登录跳/login)、请求头预处理、WAF 类拦截。但此时ctx.Input.Session尚未初始化,读不到 session 数据。 -
BeforeExec:路由已匹配成功、控制器即将执行,session 已就绪,适合做用户权限校验、参数预加载、日志记录(含 controller 名)。但对静态资源(如/static/xxx)完全不生效——这类请求压根不走路由流程。 - 别用
AfterExec做鉴权:响应体可能已部分写出,ctx.Redirect或ctx.Abort会 panic。
静态资源路径(如 /static/users/123/private/)怎么加权限?
必须用 BeforeStatic,这是唯一能拦截静态请求的钩子。其他所有过滤点都绕过它。
- 注册时 pattern 要精确匹配路径,例如:
"/static/users/:id([0-9]+)/private/*",注意正则括号必须是英文,:id是占位符,([0-9]+)才是实际匹配规则。 - 在过滤器函数里手动启动 session:
sess, _ := beego.GlobalSessions.SessionStart(ctx.ResponseWriter, ctx.Request),然后defer sess.SessionRelease(ctx.ResponseWriter),否则 session 读写失败。 - 不要依赖
ctx.Input.Session("uid")直接取值——GlobalSessions初始化后 session 才可用,且需确保app.conf中sessionon = true且sessionprovider配置正确。
常见错误:过滤器注册后没触发
八成是 pattern 写错了,或位置选错了。调试时优先检查这三点:
- pattern 是否带前导
/?Beego 要求绝对路径匹配,"*"不合法,必须写成"/*"或更具体的"/api/*"。 - 是否混淆了
BeforeRouter和BeforeStatic?访问/static/logo.png时,BeforeRouter根本不会调用。 - 是否在
main()之前注册?推荐统一放在routers/router.go的init()函数里,确保beego.Run()前完成注册。
为什么 InsertFilter 的 skip 参数几乎不用?
skip 默认为 false,仅当上一个过滤器已写入响应(比如调用了 ctx.Output.Body 或 ctx.Redirect)时,才跳过后续过滤器。实际开发中,你更应主动用 ctx.Abort() 终止链式执行,而不是靠 skip 被动跳过——后者行为隐晦,容易漏掉清理逻辑(如未释放 session)。
真正容易被忽略的是:静态资源过滤器必须手动管理 session 生命周期,且 pattern 正则中的捕获组无法直接映射到 ctx.Input.Param(":id"),得用 regexp 包自己解析 URL 路径。


















