|
|
@@ -0,0 +1,134 @@
|
|
|
+# permlib
|
|
|
+
|
|
|
+Go 权限系统接入 SDK,供产品端后台接入统一权限系统。
|
|
|
+
|
|
|
+## 安装
|
|
|
+
|
|
|
+```bash
|
|
|
+go env -w GOPRIVATE=code.clickto.dev/*
|
|
|
+go env -w GONOSUMDB=code.clickto.dev/*
|
|
|
+```
|
|
|
+
|
|
|
+```bash
|
|
|
+go get code.clickto.dev/weiym/permlib@latest
|
|
|
+```
|
|
|
+
|
|
|
+## 版本管理
|
|
|
+
|
|
|
+发布新版本时,在仓库打 tag:
|
|
|
+
|
|
|
+```bash
|
|
|
+git tag v0.1.0
|
|
|
+git push origin v0.1.0
|
|
|
+```
|
|
|
+
|
|
|
+其他项目安装指定版本:
|
|
|
+
|
|
|
+```bash
|
|
|
+go get code.clickto.dev/weiym/[email protected]
|
|
|
+```
|
|
|
+
|
|
|
+## 快速接入
|
|
|
+
|
|
|
+### 1. 初始化 Engine
|
|
|
+
|
|
|
+```go
|
|
|
+engine, err := permlib.New(permlib.Config{
|
|
|
+ ProductCode: "your-product",
|
|
|
+ AppKey: "ak_xxx",
|
|
|
+ AppSecret: "sk_xxx",
|
|
|
+ PermServerAddr: "perm-system:10002",
|
|
|
+ FieldWriteMode: permlib.FieldWriteSilent,
|
|
|
+ Callbacks: permlib.AuthCallbacks{
|
|
|
+ OnError: func(w http.ResponseWriter, r *http.Request, httpStatus int, code int, msg string) {
|
|
|
+ // 返回错误响应
|
|
|
+ },
|
|
|
+ OnSuccess: func(w http.ResponseWriter, r *http.Request, next http.HandlerFunc, user *permlib.UserInfo, hasDataPerm bool) {
|
|
|
+ if !hasDataPerm {
|
|
|
+ // 返回空数据
|
|
|
+ return
|
|
|
+ }
|
|
|
+ next(w, r)
|
|
|
+ },
|
|
|
+ },
|
|
|
+})
|
|
|
+```
|
|
|
+
|
|
|
+### 2. 注册权限(配合 permgen 插件自动生成)
|
|
|
+
|
|
|
+```go
|
|
|
+engine.RegisterPerms(perms.Perms)
|
|
|
+engine.RegisterRoutePerms(perms.RoutePerms)
|
|
|
+engine.RegisterFieldPerms(perms.FieldPerms)
|
|
|
+
|
|
|
+if err := engine.Start(context.Background()); err != nil {
|
|
|
+ panic(err)
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 3. 接入鉴权中间件(以 go-zero 为例)
|
|
|
+
|
|
|
+```go
|
|
|
+func (m *PermAuthMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
|
|
|
+ return m.engine.AuthMiddleware(next)
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+### 4. 登录 / 刷新 Token
|
|
|
+
|
|
|
+```go
|
|
|
+// 登录
|
|
|
+result, err := engine.Login(ctx, username, password)
|
|
|
+
|
|
|
+// 刷新 token
|
|
|
+result, err := engine.RefreshToken(ctx, refreshToken)
|
|
|
+```
|
|
|
+
|
|
|
+### 5. 在 Handler 中获取当前用户
|
|
|
+
|
|
|
+```go
|
|
|
+user := permlib.GetUser(r.Context())
|
|
|
+// user.UserId, user.Username, user.Perms ...
|
|
|
+```
|
|
|
+
|
|
|
+## 字段权限
|
|
|
+
|
|
|
+在 go-zero 的 api 文件中通过 `perm` tag 声明字段权限,由 permgen 插件自动生成映射表:
|
|
|
+
|
|
|
+```
|
|
|
+type CreateUserReq {
|
|
|
+ Username string `json:"username"`
|
|
|
+ Email string `json:"email" perm:"data:user:email:write"`
|
|
|
+ Salary int64 `json:"salary" perm:"data:user:salary:write"`
|
|
|
+}
|
|
|
+
|
|
|
+type UserListItem {
|
|
|
+ Username string `json:"username"`
|
|
|
+ Email string `json:"email" perm:"data:user:email:read"`
|
|
|
+ Salary int64 `json:"salary" perm:"data:user:salary:read"`
|
|
|
+}
|
|
|
+```
|
|
|
+
|
|
|
+- 写权限(`write`):用户无权时,字段从请求体中静默删除或拒绝请求(取决于 `FieldWriteMode`)
|
|
|
+- 读权限(`read`):用户无权时,字段从响应体中自动移除
|
|
|
+
|
|
|
+## 权限体系
|
|
|
+
|
|
|
+| 类型 | 格式 | 说明 |
|
|
|
+|------|------|------|
|
|
|
+| 接口权限 | `api:model:action` | 控制能否访问接口 |
|
|
|
+| 数据权限 | `data:model:action` | 控制能否看到响应数据 |
|
|
|
+| 字段读权限 | `data:model:field:read` | 控制能否读取某字段 |
|
|
|
+| 字段写权限 | `data:model:field:write` | 控制能否写入某字段 |
|
|
|
+
|
|
|
+`api:*` 和 `data:*` 权限自动成对生成,无需手动声明。
|
|
|
+
|
|
|
+## permgen 插件
|
|
|
+
|
|
|
+配合 goctl 使用,自动从 api 文件生成权限注册代码:
|
|
|
+
|
|
|
+```bash
|
|
|
+goctl api go -api your.api -dir . --plugin /path/to/permgen
|
|
|
+```
|
|
|
+
|
|
|
+生成 `internal/perms/perms.go`,包含 `Perms`、`RoutePerms`、`FieldPerms` 三个变量,在 `serviceContext` 中注册即可。
|