Beego权限校验需先标准化请求路径与方法:用ctx.Request.URL.Path获取原始路径,去除查询参数、合并重复斜杠、统一末尾斜杠;ctx.Request.Method转大写;静态资源必须用beego.BeforeStatic拦截并手动提取参数。

Beego 本身不带 RBAC,但用好 Filter + 合理的表结构 + 路径标准化,比硬塞 Casbin 更稳、更易调试、更贴合 Beego 的生命周期。
Filter 中怎么提取和标准化请求路径与方法
权限校验的第一步不是查库,而是拿到准确、可比对的 resource 和 action。很多人直接用 ctx.Input.URI() 或 ctx.Input.URL(),结果在反向代理、带查询参数、或有重复斜杠时匹配失败。
- 必须用
ctx.Request.URL.Path获取原始路径,再手动清理:去掉查询参数、合并重复斜杠、统一末尾斜杠(strings.TrimSuffix(path, "/")) -
ctx.Request.Method是大小写敏感字符串,务必转成大写(strings.ToUpper()),否则"get"会被当成非法 method - 如果 API 有版本前缀(如
/v1/users),建议在 Filter 里提前strings.TrimPrefix(path, "/v1"),避免权限表里堆满带版本号的冗余规则 - 不要依赖
ctx.Input.Param(":id")——Prepare()阶段还没解析路由参数,此时取出来是空的
ROLE_PERMISSION 关联表为什么不能只存 role_id 和 permission_id
只存两个 ID 的表结构,会导致权限粒度锁死在“能/不能访问某接口”,没法支持按钮级、字段级、甚至数据行级控制。
- 必须包含
resource字段(如"user"、"order"),对应业务资源标识,不是完整 URL - 必须包含
action字段(如"create"、"export"),允许自定义,不局限于 CRUD - 建议增加
method字段(如"POST"),显式绑定 HTTP 方法,避免 RESTful 动词歧义(比如GET /users/:id和DELETE /users/:id应该是两条不同权限) - 这样一条记录就明确表示:“角色 A 可以用 POST 方法对 user 资源执行 create 操作”,后续新增
/orders接口,只需插入几条新记录,不用改表结构
AuthFilter 里怎么映射请求到 resource:action
映射逻辑要轻量、确定、可预测。别写一堆正则去猜资源名,优先从路由定义反推,或约定路径命名规范(如 /api/v1/users → user)。
- 典型映射示例:
POST /api/v1/users→user:create;GET /api/v1/users/:id→user:read;GET /admin/reports/export→report:export - 映射函数应接收
path和method,返回标准化的code字符串(如"user:create"),这个code必须和数据库permission.code字段完全一致 - 避免在 Filter 里做 ORM 查询——每次请求都查
role_permission表,QPS 上去就拖垮服务。应预加载角色-权限关系到内存 map,按role_id索引,查code是 O(1) - 校验失败时用
ctx.Abort("403")或ctx.StopRun()立即终止,别继续往下走,也别重定向——那会掩盖真实权限问题
静态资源(/static/)权限怎么拦
/static/ 路径默认绕过所有路由匹配,BeforeRouter、BeforeExec 这些 Filter 根本不触发。你写的鉴权逻辑对它完全无效。
- 唯一有效的拦截点是
beego.BeforeStatic—— 必须在这里注册你的权限校验函数 - 此时
ctx.Input.Param(":id")不可用,所有参数得手动从ctx.Request.URL.Path里用正则提取(比如/static/users/123/private/file.pdf) - 不能调用任何控制器方法(
ctx.Controller为空),session 读取要用ctx.Input.Session.Get("user_id"),但得确认 session 已初始化 - 高频静态文件(如 PDF、图片)的权限判断必须缓存结果,否则单次请求查三次 DB,吞吐量直接腰斩
最常被忽略的一点:权限校验不是“有没有角色”,而是“当前请求是否命中任一已授权的 resource:action:method 组合”。路径标准化、method 大写、静态资源单独处理——这三个动作漏掉任何一个,系统上线后都会在某个边缘路径上静默失效。


















