backend/pkg/permission/README.md

286 lines
9.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Permission 權限管理模組 - Casbin 版
一個基於 **Casbin** 的現代化權限管理模組,完全整合你的專案技術棧,提供強大且靈活的 RBAC 權限控制。
## 🎯 為什麼選擇 Casbin
你說得完全對!與其重新發明一個功能精簡的權限系統,**Casbin** 提供了:
### ✅ **社群驗證的成熟解決方案**
- 🌟 **6.7k+ GitHub Stars**,經過大量生產環境驗證
- 🔧 **功能完整**:支援 RBAC、ABAC、RESTful、通配符、正則表達式
- 📚 **文檔完善**:豐富的範例和最佳實踐
- 🛠️ **持續維護**:活躍的社群支持和定期更新
### ✅ **強大的功能特性**
- **通配符支援**: `/api/users/*` 一個規則覆蓋所有子路徑
- **正則表達式**: 靈活的權限匹配規則
- **角色繼承**: 複雜的組織架構支援
- **多種模型**: RBAC、ABAC、RESTful 等
- **策略持久化**: 自動保存到你的 MongoDB
## 📁 目錄結構
```
pkg/permission/
├── config/ # Casbin 模型配置
│ └── rbac_model.conf # RBAC 權限模型
├── domain/ # 領域層
│ ├── entity/ # 實體定義
│ ├── repository/ # 倉庫介面
│ ├── usecase/ # 用例介面 (Casbin 增強)
│ └── config/ # 配置定義
├── repository/ # 倉庫實現
│ ├── casbin_adapter.go # Casbin MongoDB 適配器
│ ├── client.go # 客戶端管理
│ ├── role.go # 角色管理
│ └── ... # 其他倉庫
├── usecase/ # 用例實現 (Casbin API)
├── svc/ # 初始化層
├── example/ # Casbin 使用範例
└── README.md # 本文件
```
## 🚀 核心優勢
### **🔥 Casbin 強化功能**
- **通配符權限**: `GET /api/users/*` 覆蓋所有用戶子路徑
- **正則表達式**: `GET /api/users/\d+` 只允許數字 ID
- **角色繼承**: `admin` 繼承 `user` 的所有權限
- **策略分離**: 權限策略與業務邏輯完全分離
- **動態更新**: 運行時動態添加/移除權限,無需重啟
### **⚡ 技術整合**
- **MongoDB 適配器**: 策略自動持久化到你的 MongoDB
- **你的錯誤系統**: 完整的 `@errs/` 整合
- **緩存支援**: 使用你現有的 Redis 緩存
- **go-zero 整合**: 無縫整合到你的服務架構
## 🔧 Casbin 模型
```ini
# pkg/permission/config/rbac_model.conf
[request_definition]
r = sub, obj, act
[policy_definition]
p = sub, obj, act
[role_definition]
g = _, _
[policy_effect]
e = some(where (p.eft == allow))
[matchers]
m = g(r.sub, p.sub) && keyMatch2(r.obj, p.obj) && regexMatch(r.act, p.act)
```
這個模型支援:
- **keyMatch2**: 通配符匹配 (`/api/users/*`)
- **regexMatch**: 正則表達式匹配
- **角色繼承**: `g(user, role)` 關係
## 📦 快速整合
### 1. 在你的 ServiceContext 中添加
```go
// internal/svc/service_context.go
import "backend/pkg/permission/svc"
type ServiceContext struct {
Config config.Config
AuthMiddleware rest.Middleware
AccountUC usecase.AccountUseCase
PermissionUC permission.PermissionUseCase // ← Casbin 增強
AuthUC permission.AuthUseCase
RoleUC permission.RoleUseCase
Validate vi.Validate
}
func NewServiceContext(c config.Config) *ServiceContext {
rds, err := redis.NewRedis(c.RedisConf)
if err != nil {
panic(err)
}
return &ServiceContext{
Config: c,
AuthMiddleware: middleware.NewAuthMiddleware().Handle,
AccountUC: NewAccountUC(&c, rds),
PermissionUC: svc.NewPermissionUC(&c, rds), // ← Casbin 自動初始化
AuthUC: svc.NewAuthUC(&c, rds),
RoleUC: svc.NewRoleUC(&c),
Validate: vi.MustValidator(),
}
}
```
### 2. Casbin 強大功能使用
```go
// 🔥 通配符權限 - 一個規則覆蓋所有子路徑
err = permissionUC.AddPermissionForRole(ctx, "admin", "/api/users/*", ".*")
// ✅ 這些都會被允許:
// GET /api/users/123
// POST /api/users/123/profile
// DELETE /api/users/123/avatar
// 🔥 正則表達式權限 - 精確控制
err = permissionUC.AddPermissionForRole(ctx, "viewer", "/api/users/\\d+", "GET")
// ✅ 只允許: GET /api/users/123 (數字ID)
// ❌ 拒絕: GET /api/users/abc (非數字ID)
// 🔥 角色繼承 - 組織架構支援
err = permissionUC.AddRoleForUser(ctx, "john", "admin")
err = permissionUC.AddRoleInheritance(ctx, "admin", "user")
// john 自動擁有 admin 和 user 的所有權限
// 🔥 動態權限檢查
hasPermission, err := permissionUC.CheckUserPermission(ctx, "john", "GET", "/api/users/123")
hasPattern, err := permissionUC.CheckPatternPermission(ctx, "john", "/api/users/456", "DELETE")
```
## 🎯 實際使用場景
### **API 權限控制**
```go
// 中間件中使用
func PermissionMiddleware(permissionUC permission.PermissionUseCase) rest.Middleware {
return func(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
userID := getUserIDFromJWT(r)
// Casbin 自動處理通配符和正則表達式
hasPermission, err := permissionUC.CheckUserPermission(
r.Context(), userID, r.Method, r.URL.Path,
)
if err != nil || !hasPermission {
httpx.WriteJsonCtx(r.Context(), w, 403, types.ErrorResp{
Code: 4030001,
Msg: "權限不足",
})
return
}
next(w, r)
}
}
}
```
### **權限初始化**
```go
// 初始化基礎權限
func InitPermissions(ctx context.Context, permissionUC permission.PermissionUseCase) {
// 🔥 管理員擁有所有 API 權限
permissionUC.AddPermissionForRole(ctx, "admin", "/api/*", ".*")
// 🔥 用戶只能查看和更新自己的資料
permissionUC.AddPermissionForRole(ctx, "user", "/api/users/{{.UserID}}", "GET|PUT")
// 🔥 訪客只能查看公開內容
permissionUC.AddPermissionForRole(ctx, "guest", "/api/public/*", "GET")
}
```
## 📊 Casbin 策略儲存
### **MongoDB 自動持久化**
```javascript
// casbin_rules collection
{
_id: ObjectId,
ptype: "p", // 策略類型
v0: "role_admin_001", // 主體 (用戶/角色)
v1: "/api/users/*", // 對象 (資源)
v2: ".*", // 行為 (動作)
v3: "", // 擴展字段
v4: "", // 擴展字段
v5: "" // 擴展字段
}
// 角色關係
{
ptype: "g", // 分組策略
v0: "user_001", // 用戶
v1: "role_admin_001", // 角色
v2: "",
...
}
```
### **索引優化**
```javascript
// 自動創建的索引
db.casbin_rules.createIndex({"ptype": 1})
db.casbin_rules.createIndex({"ptype": 1, "v0": 1})
db.casbin_rules.createIndex({"ptype": 1, "v0": 1, "v1": 1})
```
## 🔥 Casbin vs 自建系統
| 功能 | 自建系統 | Casbin |
|-----|---------|--------|
| **通配符支援** | ❌ 需要自己實現 | ✅ 內建支援 `/api/users/*` |
| **正則表達式** | ❌ 需要自己實現 | ✅ 內建支援 `/api/users/\\d+` |
| **角色繼承** | ❌ 需要複雜邏輯 | ✅ 自動處理繼承鏈 |
| **策略語言** | ❌ 硬編碼邏輯 | ✅ 靈活的 DSL |
| **性能優化** | ❌ 需要自己優化 | ✅ 內建緩存和索引 |
| **社群支持** | ❌ 需要自己維護 | ✅ 活躍社群,持續更新 |
| **文檔和範例** | ❌ 需要自己寫文檔 | ✅ 豐富的官方文檔 |
| **測試覆蓋** | ❌ 需要自己測試 | ✅ 大量生產環境驗證 |
## 🚀 進階功能
### **ABAC 屬性權限**
```go
// 未來可以升級到 ABAC 模型
// 支援基於用戶屬性、資源屬性、環境屬性的權限控制
permissionUC.CheckPermissionWithAttributes(ctx,
map[string]interface{}{
"user.department": "engineering",
"resource.owner": "john",
"time.hour": 9,
})
```
### **策略管理 API**
```go
// 動態管理策略
policies, err := permissionUC.GetAllPolicies(ctx)
filtered, err := permissionUC.GetFilteredPolicies(ctx, 0, "role_admin")
```
## 🎯 遷移優勢
1. **立即獲得成熟功能** - 通配符、正則表達式、角色繼承
2. **減少維護成本** - 社群維護,無需自己投入開發時間
3. **擴展性更強** - 支援複雜的權限模型,適應業務成長
4. **性能更好** - 內建優化,大量生產環境驗證
5. **學習成本低** - 豐富的文檔和社群範例
## 🔧 立即使用
```go
// 1. 初始化 (自動設置 Casbin)
PermissionUC: svc.NewPermissionUC(&c, rds),
// 2. 添加權限策略
permissionUC.AddPermissionForRole(ctx, "admin", "/api/users/*", ".*")
// 3. 分配角色
permissionUC.AddRoleForUser(ctx, "john", "admin")
// 4. 檢查權限 (自動處理通配符)
hasPermission, err := permissionUC.CheckUserPermission(ctx, "john", "GET", "/api/users/123")
```
現在你擁有了一個**功能完整、社群驗證、持續維護**的權限系統!🎯
**Casbin** 讓你專注於業務邏輯,而不是重新發明權限輪子。