文档目录
glen
· 预计阅读 3 分钟

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

本文导航
第 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() 和方法名。

评论

加载评论中…

上一篇 第 3 章 访问级别:四种开关决定接口怎么校验 下一篇 第 5 章 菜单与角色授权:从零完成一次授权

BitLabs © 2026 · 论坛讨论 · 博客长文 · 文档手册