第 4 章 权限标识与路由:app:module:方法名
本文导航

第 4 章 权限标识与路由:app:module:方法名
权限标识是权限体系的「钥匙」。角色拿到的是它,Casbin 校验的也是它。这一章说明它怎么生成、怎么查、什么时候会变。
生成规则
func (i *RouterInfoBuilder) getPermissionStr(funcName string) string {
return i.appName + ":" + i.moduleEn + ":" + funcName
}
三段:
| 段 | 来源 | 示例 |
|---|---|---|
appName |
SubApp.Name() |
admin |
moduleEn |
Handler.ModuleName() 的第一个返回值 |
user |
funcName |
注册时传入的处理函数名 | Create |
所以 admin 子应用里,UserHandle 的 Create 方法:
admin:user:Create
Handler 决定中间段
func (i *UserHandle) ModuleName() (string, string) {
return "user", "用户管理"
}
- 第一个返回值进入权限标识;
- 第二个返回值只作为菜单标题的默认值。
如果返回 "user",同一子应用下所有通过 UserHandle 注册的路由都以 admin:user: 开头。
函数名怎么取
Build() 里用运行时反射取函数名:
func nameOfFunction(f any) string {
fullName := runtime.FuncForPC(reflect.ValueOf(f).Pointer()).Name()
lastIndex := strings.LastIndex(fullName, ".")
if lastIndex > 0 {
return strings.Replace(fullName[lastIndex+1:], "-fm", "", 1)
}
return fullName
}
- 普通函数:取最后一个点后的名字;
- 方法值(如
userHandle.Create):运行时名称可能带-fm后缀,会被去掉。
因此权限标识的最后一段不是 Name("创建用户") 里的中文,也不是路由路径,而是 Go 方法名。
对照表
以用户模块为例:
| 注册代码 | 权限标识 |
|---|---|
userHandle.Login |
admin:user:Login |
userHandle.Me |
admin:user:Me |
userHandle.Create |
admin:user:Create |
userHandle.Retrieve |
admin:user:Retrieve |
userHandle.Delete |
admin:user:Delete |
userHandle.AssignRolesToUser |
admin:user:AssignRolesToUser |
角色模块:
| 注册代码 | 权限标识 |
|---|---|
roleHandle.Create |
admin:role:Create |
roleHandle.AssignMenusToRole |
admin:role:AssignMenusToRole |
按钮菜单与依赖权限
Build() 在 AccessAuthorized 下自动生成按钮菜单:
i.menu.Children = append(i.menu.Children, &Menu{
Name: handleName,
Meta: Meta{Title: i.currentRouter.Name},
MenuType: MenuTypeBtn,
DependentsPermission: permissions,
})
permissions 第一项是当前接口的权限标识,后面是 Deps 声明的依赖接口权限:
r.Put("/users/:id", router.AccessAuthorized, userHandle.Update).
Deps(router.Dep{Handler: userHandle, Method: userHandle.Detail}).
Name("更新用户").
Build()
这个按钮的 DependentsPermission 就是:
[
"admin:user:Update",
"admin:user:Detail"
]
分配按钮给角色时,两个权限会一起写入 Casbin。这样页面既能调更新接口,也能调详情接口。
在哪里查当前系统的权限标识
1. 接口管理页面
后台「系统管理 / 接口管理」调用:
GET /api/v1/api
返回所有已注册路由,包含:
{
"group": "/api/v1",
"method": "POST",
"path": "/api/v1/users",
"name": "创建用户",
"module": "用户管理",
"permission": "admin:user:Create",
"accessLevel": "需要授权"
}
2. 代码里查
for _, r := range router.GetAllRoutes() {
fmt.Println(r.Method, r.Path, r.Permission, r.AccessLevel)
}
3. 数据库里查
Casbin 策略表:
SELECT * FROM casbin_rule WHERE v1 = 'admin:user:Create';
什么时候权限标识会变
以下改动都会改变标识,导致已授权角色失效:
- 修改
SubApp.Name(); - 修改
Handler.ModuleName()的第一个返回值; - 重命名 Handler 方法;
- 把方法移到另一个 Handler。
上线后应把这三段视为稳定契约。确实要改时,需要同步迁移 Casbin 策略或重新给角色分配菜单。
常见问题
同一模块下两个方法重名
不允许。权限标识会冲突,Casbin 无法区分。给方法起能表达动作的名字,例如 Create / BatchCreate。
路由 Name 与权限标识不一致
正常。Name("创建用户") 只是给人看的标题;权限标识看方法名。
接口管理里看到重复权限
通常是同一个方法被注册到多条路由上。检查 InitApi 是否重复注册,或复制粘贴时忘了改方法。
自检
- [ ] 能算出任意路由的权限标识;
- [ ] 知道
ModuleName()的英文段会进入标识; - [ ] 知道
Deps会把依赖接口权限一起挂到按钮; - [ ] 上线后不随意改
Name()、ModuleName()和方法名。
评论
加载评论中…