You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
OneAuth/docs/integration.md

251 lines
6.5 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# VBase 集成文档
本文档介绍如何将 VBase 集成到您的 Golang (Vigo) 项目中,快速实现用户管理、权限控制和组织架构功能。
## 1. 快速集成 (Quick Start)
集成 VBase 仅需简单几步:
### 1.1 引入依赖
在您的项目中引入 VBase
```go
import "github.com/veypi/vbase"
```
### 1.2 挂载路由
在您的项目根路由初始化处,挂载 VBase 路由:
```go
// 您的项目初始化代码
func init() {
// 挂载 vbase 路由到 /vbase 路径下
// 这样 vbase 的 API 将可以通过 /vb/api/auth/login 等访问
MyRouter.Extend("/vb", vbase.Router)
}
```
### 1.3 配置数据库
确保您的项目已经配置了 GORM 数据库连接VBase 将复用该连接。
```go
// VBase 会自动读取您的配置,前提是您使用了兼容的配置结构或手动设置
vbase.Config.SetDB(yourDB)
// 或者直接集成到您的项目配置中由vigo.Flags 自动加载
type AppConfig struct {
Vbase any
}
var Config = *AppConfig{
Vbase: vbase.Config,
}
```
---
## 2. 详细集成方案
### 2.1 路由集成
VBase 提供了一个标准的 `vigo.Router` 实例,包含所有用户、组织、权限相关的 API。
```go
package main
import (
"github.com/veypi/vbase"
"github.com/veypi/vigo"
)
var Router = vigo.NewRouter()
func init() {
// 1. 挂载 VBase 路由
// 建议挂载在独立的前缀下,避免路由冲突
Router.Extend("/vb", vbase.Router)
}
```
### 2.2 权限系统集成
VBase 提供了强大的 RBAC (基于角色的访问控制) 权限系统。
#### 2.2.1 初始化应用权限
在您的应用中,使用 `vbase.Auth.New` 创建应用专属的权限实例。
```go
import "github.com/veypi/vbase"
// 定义您的应用权限实例
var AppAuth = vbase.Auth.New("my_app")
func init() {
// 定义应用的默认角色
AppAuth.AddRole("admin", "管理员", "*:*") // 拥有所有权限
AppAuth.AddRole("editor", "编辑",
"article:create",
"article:update",
)
}
```
#### 2.2.2 使用权限中间件
使用 `vbase.AuthMiddleware` 进行认证,并结合 `AppAuth.Perm` 进行权限检查。
```go
func init() {
// 1. 全局认证中间件 (解析 Token, 注入 user_id, org_id)
Router.Use(vbase.AuthMiddleware())
Router.Get("/info", "获取app信息", vigo.SkipBefore, getInfo)
// 2. 路由权限控制
// 检查 "article:create" 权限
Router.Post("/articles", "发布文章", AppAuth.Perm("article:create"), createArticle)
// 检查资源所有权 (确保用户只能修改自己的文章)
// 检查 "article:update" 权限,且文章的 owner_id 必须等于当前用户 ID
Router.Patch("/articles/{id}", "更新文章", AppAuth.PermWithOwner("article:update", "id"), updateArticle)
}
```
### 2.3 配置管理
VBase 允许自定义部分配置。
```go
import "github.com/veypi/vbase"
func main() {
// 获取配置单例
cfg := vbase.Config
// 启用调试模式
cfg.Debug = true
// 设置 JWT 密钥 (建议从环境变量读取)
cfg.JwtSecret = "your-secret-key"
// 自定义短信服务提供商 (可选)
// vbase.Config.SetSmsProvider(...)
}
```
### 2.4 上下文使用
通过 `vbase.AuthMiddleware` 认证后,您可以在 Handler 中通过 `*vigo.X` 获取用户信息。
```go
func MyHandler(x *vigo.X) error {
// 获取当前用户 ID
userID := x.Get("user_id").(string)
// 获取当前组织 ID (如果有)
orgID := x.Get("org_id").(string)
// ... 业务逻辑
}
```
### 2.5 权限管理高级用法
`AppAuth` 实例提供了丰富的接口来管理和检查权限。
#### 2.5.1 复杂权限检查中间件
除了基础的 `Perm``PermWithOwner`,还支持复合权限检查:
```go
// 要求同时拥有 user:read 和 order:read 权限
Router.Get("/stats", "统计数据", AppAuth.PermAll([]string{"user:read", "order:read"}), getStats)
// 只要拥有 user:read 或 user:admin 其中之一即可
Router.Get("/users", "用户列表", AppAuth.PermAny([]string{"user:read", "user:admin"}), listUsers)
```
#### 2.5.2 代码中动态检查权限
有时需要在 Handler 内部根据业务逻辑进行动态鉴权:
```go
func someHandler(x *vigo.X) error {
userID := x.Get("user_id").(string)
orgID := x.Get("org_id").(string)
// 检查是否有 "report:export" 权限
// 注意resourceID 为空时检查通用权限,指定 resourceID 时检查特定资源权限
allowed, err := AppAuth.CheckPermission(x.Context(), userID, orgID, "report:export", "")
if err != nil || !allowed {
return vigo.ErrForbidden
}
// ...
}
```
#### 2.5.3 授予和撤销角色
您可以在业务逻辑中动态授予或撤销用户角色。
**注意**`orgID` 可以为空字符串,表示授予系统级(全局)角色。
```go
// 授予用户 "editor" 角色 (在指定组织下)
err := AppAuth.GrantRole(ctx, targetUserID, orgID, "editor")
// 撤销角色
err := AppAuth.RevokeRole(ctx, targetUserID, orgID, "editor")
```
#### 2.5.4 细粒度资源授权
如果角色机制不够灵活,可以直接授予用户对特定资源的权限:
```go
// 授予用户对 ID 为 "123" 的文章的 "read" 权限
err := AppAuth.GrantResourcePerm(ctx, targetUserID, orgID, "article:read", "123")
// 撤销资源权限
err := AppAuth.RevokeResourcePerm(ctx, targetUserID, orgID, "article:read", "123")
```
#### 2.5.5 检查资源权限
授予了细粒度资源权限后,可以通过以下两种方式进行检查:
1. **使用中间件 (推荐)**
`PermOnResource` 中间件会自动从路径参数或查询参数中获取资源ID并检查用户是否有权访问该特定资源。
```go
// 自动从路径参数 "id" 获取资源ID (如 /articles/123)
// 如果用户拥有 "article:read" 角色权限,或者被单独授予了对 "123" 的 "article:read" 权限,均可通过检查
Router.Get("/articles/{id}", "获取文章", AppAuth.PermOnResource("article:read", "id"), getArticle)
```
2. **手动检查**
在 Handler 中手动调用 `CheckPermission`
```go
func getArticle(x *vigo.X) error {
articleID := x.PathParams.Get("id")
userID := x.Get("user_id").(string)
orgID := x.Get("org_id").(string)
// 检查权限
allowed, err := AppAuth.CheckPermission(x.Context(), userID, orgID, "article:read", articleID)
if err != nil {
return err
}
if !allowed {
return vigo.ErrForbidden
}
// ...
}
```