beego中用filter实现请求级权限拦截,需在beforerouter等阶段注册过滤器,通过ctx.input.session获取user_id,查缓存或db校验权限,失败时调用ctx.abort(403)终止请求。

Beego 中如何用 Filter 实现请求级权限拦截
Beego 的权限控制最常用、也最直接的方式,就是利用内置的 Filter 机制,在请求进入 Controller 前做身份与权限校验。它不依赖第三方中间件,也不需要改写路由注册逻辑,适合大多数 RBAC 场景。
关键点在于:权限判断必须在 Prepare() 方法里完成,而不是放在每个 Get() 或 Post() 里重复写;同时要避免把权限规则硬编码进 Filter,否则后期难以维护。
-
Filter注册时需指定作用范围(全局 / 某个 Controller / 某个方法),推荐用beego.InsertFilter("/admin/*", beego.BeeApp.Handlers, authFilter)控制前缀路径 - 从
ctx.Input.Session.Get("user_id")获取当前用户,再查数据库或缓存拿到其role_code或permission_list - 权限匹配建议用白名单方式:比如
map[string][]string{"AdminController": {"Create", "Delete"}},而非每次拼接字符串做strings.Contains判断 - 校验失败时务必调用
ctx.Abort(403, "Forbidden"),否则请求会继续向下执行
为什么 AuthController 不该承担权限分配逻辑
初学者常把「登录」和「授权」混在一起,误以为在 AuthController.Login() 里查完用户角色后,顺手把权限列表塞进 Session 就算完成权限管理——这会导致两个实际问题:
- Session 存储膨胀:如果权限是细粒度菜单/按钮级(如
["user:edit", "order:refund"]),一次存几十个字符串,对 Redis 或内存 Session 都是负担 - 权限变更不实时:用户在后台被移除某个权限后,已登录用户的 Session 不会自动失效,得等过期或手动清理
- 更稳妥的做法是只存
user_id和role_id,每次请求时按需查权限(配合本地缓存如beego.Cache减少 DB 压力)
models.User.HasPermission() 怎么设计才不容易出错
权限校验逻辑下沉到 Model 层,能提升复用性和测试性。但 Beego 默认没有 ORM 权限关联支持,容易写出 N+1 查询或漏掉 JOIN 条件。
- 不要在
HasPermission内部直接写o.QueryTable("user_role").Filter(...).All(&roles)后再循环查权限表;应一次性 JOIN 查询:o.QueryTable("permission").Filter("role__user__id", uid).Filter("code", code).Exist() - 参数
code必须是预定义常量(如const PermUserDelete = "user:delete"),禁止拼接用户输入,防止越权绕过 - 返回值建议用
bool, error二元组,方便上层统一处理 DB 错误(比如缓存击穿时回源失败,应记录日志并拒绝访问,而不是 panic)
Beego 2.x 升级后 Session 权限校验突然失效?
Beego 2.0 起默认 Session 引擎从 memory 改为 file,且 SessionOn 配置项被废弃,改用 EnableSession。很多老项目升级后发现 ctx.Input.Session.Get() 总是返回 nil,本质是 Session 未正确初始化。
- 检查配置文件是否含
EnableSession = true(conf/app.conf),且SessionProvider设置合理(开发环境可用memory,生产务必用redis) - 确认 Controller 继承的是
beego.Controller,不是自定义基类中漏掉了c.EnableRender = false这类干扰 Session 初始化的设置 - 调试时可加一行
beego.Debug("session id:", ctx.Input.CruSession.SessionID()),若输出空字符串,说明 Session 根本没启动
权限系统真正难的不是写几个 if 判断,而是权限变更的传播时机、缓存一致性、以及错误时的日志上下文——这些地方不显眼,但线上出问题时第一个被怀疑。











