必须用beego.beforerouter,因其在路由匹配前执行,可统一拦截未授权路径;误用beforeexec会绕过静态资源校验,prepare中校验则响应不统一。

Beego 中权限校验该放在哪个 Filter 阶段
必须用 beego.BeforeRouter,不能用 beego.BeforeExec 或 beego.Beforerouter(注意大小写)——后者根本不存在,是常见拼写错误。
原因很直接:权限判断需要在路由匹配前完成,否则无法统一拦截未授权路径;但又不能晚于路由解析,否则控制器里的 Prepare() 方法可能已执行部分业务逻辑。而 beego.BeforeRouter 正好卡在这个临界点:请求刚进来、还没查路由表,此时读 session、取用户角色、预判能否访问当前 ctx.Request.URL.Path 和 ctx.Request.Method 最安全。
- 若误用
beego.BeforeExec,会导致静态资源(如/static/xxx)完全绕过校验 - 若在控制器
Prepare()里做权限,意味着路由已命中、资源已加载,出错时响应状态码难统一(比如本该 403 却返回 200 + 空内容) - RBAC 场景下,建议把权限检查逻辑抽成独立函数,例如
CheckPermission(ctx *context.Context, resource string, action string) bool,避免每个 Filter 重复写 session 解析和 DB 查询
如何让 /static/ 下的私有文件也走权限控制
静态资源默认不进路由流程,beego.BeforeRouter 对它完全无效。唯一可靠入口是 beego.BeforeStatic。
比如你要保护 /static/users/123/private/report.pdf,就得注册过滤器匹配路径:"/static/users/:id([0-9]+)/private/*",并确保在 routers/router.go 的 init() 函数里调用 beego.InsertFilter()。
- 正则部分必须写成
([0-9]+),不能只写:id,否则 Beego 不会提取参数到ctx.Input.Param(":id") -
beego.BeforeStatic的 handler 函数里,要手动调用ctx.Abort(403)或重定向,不能靠 return —— 它不会自动终止后续处理 - 如果同时用了 Nginx 做静态文件代理,得关掉
beego.StaticDir,否则 Beego 根本收不到这些请求
RBAC 权限数据怎么映射到 Beego 路由
权限表里存的不是「能访问 /user/list」,而是「能执行 user:list:read」这类操作标识符,再通过中间件做运行时匹配。
Beego 路由本身不带权限元信息,所以得靠约定:把控制器方法名 + HTTP 方法 + 资源名拼成权限 key。例如 UserController.List() 处理 GET /api/v1/users → 权限 key 是 "user:list:get"。
- 不要把权限硬编码在
Router()参数里,比如"get:List;post:Create"后面加注释,Beego 不解析也不传递 - 推荐在
controllers/base.go里定义一个GetPermissionKey()方法,由各 Controller 继承后覆写,避免字符串拼接出错 - 数据库里
ROLE_PERMISSION表的permission_code字段值必须和代码中生成的 key 完全一致,大小写、冒号、连字符都不能错
为什么 AuthFilter 里获取不到 session 用户信息
大概率是 session 配置没生效,或者 Filter 插入时机太早——beego.BeforeRouter 虽然够早,但比 session 初始化还早一点。
Beego 的 session 模块默认在 beego.Run() 内部初始化,而 Filter 是在 init() 阶段注册的。所以你在 Filter 里直接调 ctx.Input.Session.Get("uid") 可能返回 nil。
- 正确做法:先调
ctx.Input.CruSession触发 session 初始化,再 get 数据,例如:ctx.Input.CruSession = ctx.Input.CruSession // 强制初始化 - 检查
conf/app.conf是否设置了sessionon = true和有效的sessionprovider(如memory或redis) - 开发期可加日志验证:
beego.Debug("session id:", ctx.Input.CruSession.SessionID()),如果输出空字符串,说明 session 没起来
RBAC 权限系统最难的不是数据库建模或中间件写法,而是权限粒度与 URL 结构的对齐方式——URL 改动一丁点,所有权限 key 就得批量更新,上线前务必用脚本扫一遍 controller 方法签名和数据库记录是否一致。











