beego中添加中间件通过注册过滤器实现,需在beego.run()前调用beego.insertfilter(),按阶段(如beforerouter、beforestatic)注册,静态资源权限校验必须用beforestatic阶段并手动解析url参数。

Beego 中添加中间件不是靠 Use() 或 UseMiddleware() 这类函数,而是通过注册 过滤器(Filter) 实现的。你写一个函数,再用 beego.InsertFilter() 注册进去,就完成了。
beego.InsertFilter() 的调用位置和时机很关键
- 必须在
beego.Run()之前注册,通常放在main()函数开头或init()里 - 如果注册晚了(比如在某个 Controller 里才调),它根本不会生效
- 多个过滤器按注册顺序执行,但注意:Beego 的过滤器分阶段,阶段不同,触发时机完全不同
常见阶段参数:
-
beego.BeeApp.Handlers:全局请求入口(最外层) -
beego.BeforeRouter:路由匹配前,所有请求都走这里(含/static吗?不,不含) -
beego.AfterStatic:静态文件响应后(极少用) -
beego.BeforeStatic:唯一能拦截/static/路径的阶段,比如/static/users/123/private/file.pdf -
beego.BeforeExec:路由匹配成功、即将进 Controller 前(这时ctx.Input.Param()才可用)
容易踩的坑:
- 把权限校验写在
BeforeRouter,结果发现/static/xxx完全不触发——因为静态路由绕过了整个路由系统 - 在
BeforeStatic里调用ctx.Controller或ctx.Input.Crued()——这些字段还没初始化,会 panic - 用
ctx.Input.Param(":id")提取参数失败——BeforeStatic阶段参数未解析,得自己用正则从ctx.Request.URL.Path里抠
中间件函数签名必须是 func(*context.Context)
Beego 的中间件本质是过滤器函数,签名固定:
func AuthFilter(ctx *context.Context) {
path := ctx.Request.URL.Path
if strings.HasPrefix(path, "/admin/") {
// 手动提取 token 或 session
sessUserID := ctx.Input.Session.Get("user_id")
if sessUserID == nil {
ctx.Abort(401, "Unauthorized")
return
}
}
ctx.Next() // 继续后续流程(下一个过滤器或控制器)
}
注意点:
- 必须显式调用
ctx.Next(),否则链路中断,后续过滤器和 Controller 都不会执行 -
ctx.Abort(statusCode, message)是终止请求的标准方式,不要用return就完事(它只退出当前函数,不阻止后续逻辑) - 不要 defer
ctx.Next(),它不是回调,是同步控制流跳转
静态资源权限控制必须用 beego.BeforeStatic
这是 Beego 最反直觉但最关键的一点:/static/ 下的请求(如 /static/uploads/abc.jpg)完全不经过路由匹配,所以 BeforeRouter、BeforeExec 全部失效。
正确做法:
beego.InsertFilter("/static/*", beego.BeforeStatic, AuthFilter)
其中 "/static/*" 是路径匹配模式(支持通配),不是正则;AuthFilter 函数里不能依赖 ctx.Input.Param(),得自己 parse URL:
path := ctx.Request.URL.Path
re := regexp.MustCompile(`/static/users/(\d+)/private/`)
matches := re.FindStringSubmatchIndex([]byte(path))
if len(matches) == 0 {
ctx.Abort(403, "Forbidden")
return
}
userID, _ := strconv.Atoi(string(path[matches[0][2]:matches[0][3]]))
// 再查缓存或 RBAC 规则
别每次请求都查数据库——QPS 上去会拖垮服务。
Beego 的中间件机制表面简单,但阶段语义和静态路径处理是高频翻车点。真正难的不是“怎么加”,而是“加在哪一阶段”以及“那个阶段到底能访问什么上下文”。漏掉 BeforeStatic 这个环节,整个权限体系对静态资源就是裸奔。











