backend/pkg/permission/README.md

729 lines
17 KiB
Markdown
Raw Normal View History

2025-10-06 08:28:39 +00:00
# Permission Module
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
一個完整的 Go 權限管理模組,提供 JWT 令牌管理、RBAC基於角色的訪問控制以及權限樹管理功能。
## 📋 目錄
- [功能特性](#功能特性)
- [架構設計](#架構設計)
- [目錄結構](#目錄結構)
- [快速開始](#快速開始)
- [API 文檔](#api-文檔)
- [配置說明](#配置說明)
- [測試](#測試)
- [最佳實踐](#最佳實踐)
## 🎯 功能特性
### 1. JWT 令牌管理
- ✅ Access Token 與 Refresh Token 機制
- ✅ One-Time Token 支持(一次性令牌)
- ✅ 設備追蹤與管理
- ✅ 令牌黑名單機制
- ✅ 多設備登錄限制
- ✅ 令牌自動過期與刷新
### 2. RBAC 權限控制
- ✅ 層級式權限結構(權限樹)
- ✅ 角色與權限關聯管理
- ✅ 使用者與角色關聯管理
- ✅ 動態權限檢查
- ✅ HTTP API 權限映射
- ✅ 權限繼承(父權限自動包含)
### 3. 資料持久化
- ✅ Redis 令牌存儲與快取
- ✅ MongoDB 權限/角色數據存儲
- ✅ 批量查詢優化(避免 N+1
- ✅ 軟刪除支持
### 4. 安全特性
- ✅ JWT 簽名驗證
- ✅ 令牌黑名單
- ✅ 設備指紋追蹤
- ✅ 循環依賴檢測
- ✅ 管理員權限特殊處理
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
## 🏗️ 架構設計
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
本模組遵循 **Clean Architecture** 設計原則:
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
```
pkg/permission/
├── domain/ # 領域層(核心業務邏輯)
│ ├── entity/ # 實體定義
│ ├── repository/ # Repository 介面
│ ├── usecase/ # UseCase 介面
│ ├── config/ # 配置定義
│ ├── permission/ # 權限類型定義
│ └── token/ # 令牌類型定義
├── usecase/ # UseCase 實現層
│ ├── token.go # 令牌業務邏輯
│ ├── permission_usecase.go # 權限業務邏輯
│ ├── role_usecase.go # 角色業務邏輯
│ ├── role_permission_usecase.go # 角色權限業務邏輯
│ ├── user_role_usecase.go # 使用者角色業務邏輯
│ └── permission_tree.go # 權限樹結構
├── repository/ # Repository 實現層(數據訪問)
│ ├── token_model.go # Redis 令牌存儲
│ ├── permission.go # MongoDB 權限存儲
│ ├── role.go # MongoDB 角色存儲
│ ├── role_permission.go # MongoDB 角色權限存儲
│ └── user_role.go # MongoDB 使用者角色存儲
└── mock/ # Mock 實現(測試用)
```
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
### 依賴關係圖
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
```
┌─────────────────┐
│ HTTP Handler │
└────────┬────────┘
┌─────────────────┐
│ UseCase │ ◄─── 業務邏輯層
│ - Token │
│ - Permission │
│ - Role │
│ - UserRole │
└────────┬────────┘
┌─────────────────┐
│ Repository │ ◄─── 數據訪問層
│ - Redis │
│ - MongoDB │
└────────┬────────┘
┌─────────────────┐
│ Storage │ ◄─── 存儲層
│ - Redis │
│ - MongoDB │
└─────────────────┘
```
2025-10-06 08:28:39 +00:00
2025-10-10 15:25:36 +00:00
## 📁 目錄結構
2025-10-06 08:28:39 +00:00
2025-10-10 15:25:36 +00:00
### domain/ - 領域層
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
#### entity/ - 實體定義
- `token.go` - 令牌實體Token, Ticket, Blacklist
- `permission.go` - 權限實體
- `role.go` - 角色實體
- `role_permission.go` - 角色權限關聯實體
- `user_role.go` - 使用者角色實體
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
#### repository/ - Repository 介面
定義數據訪問接口,與具體實現解耦
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
#### usecase/ - UseCase 介面
定義業務邏輯接口,規範業務操作
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
#### config/ - 配置定義
- `config.go` - 模組配置結構
- `errors.go` - 配置錯誤定義
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
#### permission/ - 權限類型
- `types.go` - 權限狀態、類型、集合定義
#### token/ - 令牌類型
- `token_type.go` - 令牌類型常量
- `grant_type.go` - 授權類型定義
### usecase/ - 業務邏輯實現
#### 令牌管理
- `token.go` - JWT 令牌生成、驗證、刷新
- `token_jwt.go` - JWT 編解碼
- `token_claims.go` - JWT Claims 處理
#### RBAC 管理
- `permission_usecase.go` - 權限管理
- `role_usecase.go` - 角色管理
- `role_permission_usecase.go` - 角色權限管理
- `user_role_usecase.go` - 使用者角色管理
- `permission_tree.go` - 權限樹結構與操作
### repository/ - 數據訪問實現
- `token_model.go` - Redis 令牌存儲實現
- `permission.go` - MongoDB 權限存儲實現
- `role.go` - MongoDB 角色存儲實現
- `role_permission.go` - MongoDB 角色權限存儲實現
- `user_role.go` - MongoDB 使用者角色存儲實現
### mock/ - Mock 實現
自動生成的 Mock 實現,用於單元測試
## 🚀 快速開始
### 1. 安裝依賴
```bash
go get backend/pkg/permission
2025-10-06 08:28:39 +00:00
```
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
### 2. 配置
2025-10-03 08:38:12 +00:00
2025-10-06 08:28:39 +00:00
```go
import (
2025-10-10 15:25:36 +00:00
"backend/pkg/permission/domain/config"
2025-10-06 08:28:39 +00:00
"backend/pkg/permission/usecase"
2025-10-10 15:25:36 +00:00
"backend/pkg/permission/repository"
2025-10-06 08:28:39 +00:00
)
2025-10-10 15:25:36 +00:00
// 配置
cfg := &config.Config{
Token: config.TokenConfig{
Secret: "your-secret-key",
Expired: config.ExpiredConfig{
Seconds: 900, // 15 分鐘
},
RefreshExpires: config.ExpiredConfig{
Seconds: 604800, // 7 天
},
Issuer: "playone-backend",
MaxTokensPerUser: 10,
MaxTokensPerDevice: 5,
},
Role: config.RoleConfig{
AdminRoleUID: "ADMIN",
UIDPrefix: "ROLE",
UIDLength: 10,
},
}
```
### 3. 初始化 Repository
```go
// Redis 令牌存儲
redisClient := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
})
tokenRepo := repository.NewTokenRepository(repository.TokenRepositoryParam{
2025-10-06 08:28:39 +00:00
Redis: redisClient,
})
2025-10-10 15:25:36 +00:00
// MongoDB 存儲
mongoConf := &mongo.Conf{
Host: "localhost:27017",
Database: "permission",
User: "admin",
Password: "password",
}
permRepo := repository.NewPermissionRepository(repository.PermissionRepositoryParam{
Conf: mongoConf,
CacheConf: cache.CacheConf{},
})
roleRepo := repository.NewRoleRepository(repository.RoleRepositoryParam{
Conf: mongoConf,
CacheConf: cache.CacheConf{},
})
rolePermRepo := repository.NewRolePermissionRepository(repository.RolePermissionRepositoryParam{
Conf: mongoConf,
CacheConf: cache.CacheConf{},
})
userRoleRepo := repository.NewUserRoleRepository(repository.UserRoleRepositoryParam{
Conf: mongoConf,
CacheConf: cache.CacheConf{},
})
```
### 4. 初始化 UseCase
```go
// 權限 UseCase
permUC := usecase.NewPermissionUseCase(usecase.PermissionUseCaseParam{
PermRepo: permRepo,
RolePermRepo: rolePermRepo,
RoleRepo: roleRepo,
UserRoleRepo: userRoleRepo,
})
// 角色權限 UseCase
rolePermUC := usecase.NewRolePermissionUseCase(usecase.RolePermissionUseCaseParam{
PermRepo: permRepo,
RolePermRepo: rolePermRepo,
RoleRepo: roleRepo,
UserRoleRepo: userRoleRepo,
PermUseCase: permUC,
AdminRoleUID: cfg.Role.AdminRoleUID,
})
// 角色 UseCase
roleUC := usecase.NewRoleUseCase(usecase.RoleUseCaseParam{
RoleRepo: roleRepo,
UserRoleRepo: userRoleRepo,
RolePermUseCase: rolePermUC,
Config: usecase.RoleUseCaseConfig{
AdminRoleUID: cfg.Role.AdminRoleUID,
UIDPrefix: cfg.Role.UIDPrefix,
UIDLength: cfg.Role.UIDLength,
},
})
// 使用者角色 UseCase
userRoleUC := usecase.NewUserRoleUseCase(usecase.UserRoleUseCaseParam{
UserRoleRepo: userRoleRepo,
RoleRepo: roleRepo,
})
// 令牌 UseCase
tokenUC := usecase.NewTokenUseCase(usecase.TokenUseCaseParam{
2025-10-06 08:28:39 +00:00
TokenRepo: tokenRepo,
2025-10-10 15:25:36 +00:00
Config: cfg,
2025-10-06 08:28:39 +00:00
})
2025-10-03 08:38:12 +00:00
```
2025-10-10 15:25:36 +00:00
## 📚 API 文檔
2025-10-06 08:28:39 +00:00
2025-10-10 15:25:36 +00:00
### 令牌管理 API
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
#### 生成令牌
2025-10-06 08:28:39 +00:00
```go
req := entity.AuthorizationReq{
2025-10-10 15:25:36 +00:00
GrantType: token.PasswordCredentials.ToString(),
Data: map[string]string{
2025-10-06 08:28:39 +00:00
"uid": "user123",
"role": "admin",
},
2025-10-10 15:25:36 +00:00
DeviceID: "device123",
2025-10-06 08:28:39 +00:00
}
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
tokenResp, err := tokenUC.NewToken(ctx, req)
// tokenResp.AccessToken
// tokenResp.RefreshToken
// tokenResp.ExpiresIn
```
#### 刷新令牌
```go
req := entity.RefreshTokenReq{
RefreshToken: "old-refresh-token",
DeviceID: "device123",
2025-10-06 08:28:39 +00:00
}
2025-10-10 15:25:36 +00:00
tokenResp, err := tokenUC.RefreshToken(ctx, req)
2025-10-06 08:28:39 +00:00
```
2025-10-10 15:25:36 +00:00
#### 驗證令牌
```go
isValid := tokenUC.IsAccessTokenValid(ctx, accessToken)
```
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
#### 取消令牌
2025-10-03 08:38:12 +00:00
```go
2025-10-10 15:25:36 +00:00
err := tokenUC.CancelToken(ctx, tokenID)
```
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
#### 黑名單令牌
```go
err := tokenUC.BlacklistToken(ctx, entity.BlacklistTokenReq{
TokenID: tokenID,
Reason: "User logout",
})
```
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
### 權限管理 API
#### 獲取所有權限
```go
permissions, err := permUC.GetAll(ctx)
```
#### 獲取權限樹
```go
tree, err := permUC.GetTree(ctx)
2025-10-06 08:28:39 +00:00
```
2025-10-10 15:25:36 +00:00
#### 根據 HTTP 路徑獲取權限
```go
perm, err := permUC.GetByHTTP(ctx, "/api/users", "GET")
```
2025-10-06 08:28:39 +00:00
2025-10-10 15:25:36 +00:00
#### 展開權限(包含父權限)
2025-10-06 08:28:39 +00:00
```go
2025-10-10 15:25:36 +00:00
perms := permission.Permissions{
"user.list": permission.Open,
2025-10-03 08:38:12 +00:00
}
2025-10-10 15:25:36 +00:00
expanded, err := permUC.ExpandPermissions(ctx, perms)
// expanded 將包含 "user" 和 "user.list"
2025-10-03 08:38:12 +00:00
```
2025-10-10 15:25:36 +00:00
### 角色管理 API
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
#### 創建角色
2025-10-03 08:38:12 +00:00
```go
2025-10-10 15:25:36 +00:00
req := usecase.CreateRoleRequest{
ClientID: 1,
Name: "管理員",
Permissions: permission.Permissions{
"user.list": permission.Open,
"user.create": permission.Open,
},
2025-10-06 08:28:39 +00:00
}
2025-10-10 15:25:36 +00:00
role, err := roleUC.Create(ctx, req)
2025-10-06 08:28:39 +00:00
```
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
#### 更新角色
```go
name := "高級管理員"
req := usecase.UpdateRoleRequest{
Name: &name,
Permissions: permission.Permissions{
"user.list": permission.Open,
"user.create": permission.Open,
"user.delete": permission.Open,
},
}
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
role, err := roleUC.Update(ctx, "ROLE0000000001", req)
```
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
#### 刪除角色
```go
err := roleUC.Delete(ctx, "ROLE0000000001")
```
#### 分頁查詢角色
```go
filter := usecase.RoleFilterRequest{
ClientID: 1,
Name: "管理",
2025-10-03 08:38:12 +00:00
}
2025-10-10 15:25:36 +00:00
page, err := roleUC.Page(ctx, filter, 1, 10)
// page.List - 角色列表(含使用者數量)
// page.Total - 總數
2025-10-03 08:38:12 +00:00
```
2025-10-10 15:25:36 +00:00
### 角色權限管理 API
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
#### 獲取角色權限
2025-10-06 08:28:39 +00:00
```go
2025-10-10 15:25:36 +00:00
perms, err := rolePermUC.GetByRoleUID(ctx, "ROLE0000000001")
2025-10-03 08:38:12 +00:00
```
2025-10-10 15:25:36 +00:00
#### 獲取使用者權限
2025-10-06 08:28:39 +00:00
```go
2025-10-10 15:25:36 +00:00
userPerms, err := rolePermUC.GetByUserUID(ctx, "user123")
// userPerms.RoleUID
// userPerms.RoleName
// userPerms.Permissions
```
#### 更新角色權限
```go
perms := permission.Permissions{
"user.list": permission.Open,
"user.create": permission.Open,
2025-10-06 08:28:39 +00:00
}
2025-10-10 15:25:36 +00:00
err := rolePermUC.UpdateRolePermissions(ctx, "ROLE0000000001", perms)
2025-10-03 08:38:12 +00:00
```
2025-10-10 15:25:36 +00:00
#### 檢查權限
```go
result, err := rolePermUC.CheckPermission(ctx, "ROLE0000000001", "/api/users", "GET")
// result.Allowed - 是否允許
// result.PermissionName - 權限名稱
// result.PlainCode - 是否有 plain_code 權限
```
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
### 使用者角色管理 API
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
#### 指派角色給使用者
```go
req := usecase.AssignRoleRequest{
UserUID: "user123",
RoleUID: "ROLE0000000001",
Brand: "brand1",
}
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
userRole, err := userRoleUC.Assign(ctx, req)
```
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
#### 更新使用者角色
2025-10-03 08:38:12 +00:00
```go
2025-10-10 15:25:36 +00:00
userRole, err := userRoleUC.Update(ctx, "user123", "ROLE0000000002")
```
2025-10-06 08:28:39 +00:00
2025-10-10 15:25:36 +00:00
#### 移除使用者角色
```go
err := userRoleUC.Remove(ctx, "user123")
```
2025-10-06 08:28:39 +00:00
2025-10-10 15:25:36 +00:00
#### 獲取角色的所有使用者
```go
userRoles, err := userRoleUC.GetByRole(ctx, "ROLE0000000001")
```
## ⚙️ 配置說明
### Token 配置
```yaml
token:
secret: "your-jwt-secret-key" # JWT 簽名密鑰
expired:
seconds: 900 # Access Token 過期時間(秒)
refresh_expires:
seconds: 604800 # Refresh Token 過期時間(秒)
issuer: "playone-backend" # 發行者
max_tokens_per_user: 10 # 每個使用者最大令牌數
max_tokens_per_device: 5 # 每個設備最大令牌數
enable_device_tracking: true # 是否啟用設備追蹤
```
### Role 配置
```yaml
role:
admin_role_uid: "ADMIN" # 管理員角色 UID
uid_prefix: "ROLE" # 角色 UID 前綴
uid_length: 10 # UID 數字長度
```
### RBAC 配置
```yaml
rbac:
enable_cache: true # 是否啟用快取
cache_ttl: 3600 # 快取過期時間(秒)
```
## 🧪 測試
### 運行所有測試
```bash
go test ./pkg/permission/... -v
```
### 運行特定測試
```bash
# 令牌測試
go test ./pkg/permission/usecase -run TestToken -v
# 權限樹測試
go test ./pkg/permission/usecase -run TestPermissionTree -v
# Repository 測試
go test ./pkg/permission/repository -v
2025-10-03 08:38:12 +00:00
```
2025-10-10 15:25:36 +00:00
### 測試覆蓋率
```bash
go test ./pkg/permission/... -cover
```
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
### 生成覆蓋率報告
```bash
go test ./pkg/permission/... -coverprofile=coverage.out
go tool cover -html=coverage.out -o coverage.html
```
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
## 💡 最佳實踐
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
### 1. 令牌管理
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
#### ✅ 推薦做法
```go
// 使用 Refresh Token 自動刷新
if tokenUC.IsAccessTokenValid(ctx, accessToken) {
// 使用令牌
} else {
// 嘗試刷新
newToken, err := tokenUC.RefreshToken(ctx, refreshReq)
if err != nil {
// 要求重新登錄
}
}
```
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
#### ❌ 避免做法
```go
// 不要在每次請求都生成新令牌
// 不要將令牌存儲在不安全的地方
// 不要在客戶端解析 Refresh Token
```
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
### 2. 權限檢查
2025-10-06 08:28:39 +00:00
2025-10-10 15:25:36 +00:00
#### ✅ 推薦做法
```go
// 使用權限檢查中間件
func AuthMiddleware(rolePermUC usecase.RolePermissionUseCase) gin.HandlerFunc {
return func(c *gin.Context) {
roleUID := c.GetString("role_uid")
result, err := rolePermUC.CheckPermission(
c.Request.Context(),
roleUID,
c.Request.URL.Path,
c.Request.Method,
)
if err != nil || !result.Allowed {
c.AbortWithStatus(http.StatusForbidden)
return
}
c.Next()
}
}
```
2025-10-06 08:28:39 +00:00
2025-10-10 15:25:36 +00:00
#### ❌ 避免做法
```go
// 不要在每個 Handler 中重複權限檢查代碼
// 不要硬編碼權限名稱
// 不要跳過權限檢查
```
2025-10-06 08:28:39 +00:00
2025-10-10 15:25:36 +00:00
### 3. 權限設計
2025-10-06 08:28:39 +00:00
2025-10-10 15:25:36 +00:00
#### ✅ 推薦做法
```go
// 使用層級式權限結構
// 例如:
// - user
// - user.list
// - user.create
// - user.update
// - user.delete
// 父權限會自動包含,只需設置子權限即可
perms := permission.Permissions{
"user.list": permission.Open,
}
// 展開後會自動包含 "user"
```
2025-10-06 08:28:39 +00:00
2025-10-10 15:25:36 +00:00
#### ❌ 避免做法
```go
// 不要創建過深的權限層級(建議 ≤ 3 層)
// 不要使用過於細緻的權限粒度
// 不要創建循環依賴的權限
```
### 4. 角色管理
#### ✅ 推薦做法
```go
// 使用預定義角色
const (
RoleAdmin = "ADMIN"
RoleManager = "MANAGER"
RoleEmployee = "EMPLOYEE"
)
2025-10-06 08:28:39 +00:00
2025-10-10 15:25:36 +00:00
// 定期檢查無使用者的角色
roles, _ := roleUC.Page(ctx, filter, 1, 100)
for _, role := range roles.List {
if role.UserCount == 0 {
// 考慮刪除或停用
}
}
```
2025-10-06 08:28:39 +00:00
2025-10-10 15:25:36 +00:00
#### ❌ 避免做法
```go
// 不要創建過多的角色
// 不要刪除有使用者的角色
// 不要頻繁修改角色權限
```
2025-10-06 08:28:39 +00:00
2025-10-10 15:25:36 +00:00
## 🔐 安全建議
1. **JWT 密鑰管理**
- 使用強密鑰(至少 32 字元)
- 定期輪換密鑰
- 不要將密鑰硬編碼在代碼中
2. **令牌過期設置**
- Access Token: 15 分鐘 - 1 小時
- Refresh Token: 7 - 30 天
- One-Time Token: 5 - 10 分鐘
3. **設備追蹤**
- 啟用設備指紋追蹤
- 限制每個設備的令牌數量
- 檢測異常登錄行為
4. **權限檢查**
- 在所有 API 端點進行權限檢查
- 使用白名單而非黑名單
- 記錄權限拒絕事件
## 📝 資料庫設計
### MongoDB Collections
#### permissions
```json
{
"_id": ObjectId,
"parent_id": ObjectId,
"name": "user.list",
"http_method": "GET",
"http_path": "/api/users",
"status": 1,
"type": 1,
"create_time": 1234567890,
"update_time": 1234567890
}
```
2025-10-06 08:28:39 +00:00
2025-10-10 15:25:36 +00:00
#### roles
```json
{
"_id": ObjectId,
"client_id": 1,
"uid": "ROLE0000000001",
"name": "管理員",
"status": 1,
"create_time": 1234567890,
"update_time": 1234567890
}
```
2025-10-06 08:28:39 +00:00
2025-10-10 15:25:36 +00:00
#### role_permissions
```json
{
"_id": ObjectId,
"role_id": ObjectId,
"permission_id": ObjectId,
"create_time": 1234567890,
"update_time": 1234567890
}
```
2025-10-06 08:28:39 +00:00
2025-10-10 15:25:36 +00:00
#### user_roles
```json
{
"_id": ObjectId,
"brand": "brand1",
"uid": "user123",
"role_id": "ROLE0000000001",
"status": 1,
"create_time": 1234567890,
"update_time": 1234567890
}
```
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
### Redis Keys
2025-10-03 08:38:12 +00:00
2025-10-10 15:25:36 +00:00
```
permission:access_token:{token_id} # Access Token
permission:refresh_token:{token_id} # Refresh Token
permission:device_token:{device_id} # Device Token List
permission:uid_token:{uid} # User Token List
permission:ticket:{ticket} # One-Time Token
permission:blacklist:{token_id} # Token Blacklist
```