Skip to content

权限控制

VEF Framework 提供了灵活的权限控制机制,支持基于令牌的权限验证。

权限令牌

定义 API 权限

go
// Set permission for prebuilt API
apis.NewFindPageApi[models.User, payloads.UserSearch]().
    WithPermission("user:read")

apis.NewCreateApi[models.User, payloads.UserParams]().
    WithPermission("user:create")

apis.NewUpdateApi[models.User, payloads.UserParams]().
    WithPermission("user:update")

apis.NewDeleteApi[models.User]().
    WithPermission("user:delete")

自定义 API 权限

go
// Register API with permission
resource.RegisterApiWithPermission(
    "reset_password",
    "user:reset_password",
    resource.ResetPassword,
)

权限命名约定

推荐使用 {module}:{action} 格式:

权限令牌说明
user:read查看用户
user:create创建用户
user:update更新用户
user:delete删除用户
user:export导出用户
order:approve审批订单

权限检查

自动权限检查

配置了权限的 API 会自动进行权限检查:

go
// This API requires "user:read" permission
apis.NewFindPageApi[models.User, payloads.UserSearch]().
    WithPermission("user:read")

// Request without permission will receive 403 Forbidden

手动权限检查

go
func (r *UserResource) AdminOperation(ctx fiber.Ctx) error {
    currentUser := contextx.GetCurrentUser(ctx)
    
    // Check single permission
    if !currentUser.HasPermission("admin:manage") {
        return api.Forbidden(ctx, "Permission denied")
    }
    
    // Check any of permissions
    if !currentUser.HasAnyPermission("admin:manage", "super:admin") {
        return api.Forbidden(ctx, "Permission denied")
    }
    
    // Check all permissions
    if !currentUser.HasAllPermissions("user:read", "user:update") {
        return api.Forbidden(ctx, "Permission denied")
    }
    
    return api.Success(ctx, nil)
}

权限加载

实现 PermissionLoader

go
package auth

import (
    "github.com/ilxqx/vef-framework-go/auth"
    "github.com/ilxqx/vef-framework-go/orm"
)

type PermissionLoaderImpl struct{}

func NewPermissionLoader() auth.PermissionLoader {
    return &PermissionLoaderImpl{}
}

// LoadPermissions loads permissions for user
func (l *PermissionLoaderImpl) LoadPermissions(userId string, roleIds []string) ([]string, error) {
    var permissions []string
    
    // Load role permissions
    err := orm.DB().
        Table("role_permissions rp").
        Select("DISTINCT p.token").
        Joins("JOIN permissions p ON p.id = rp.permission_id").
        Where("rp.role_id IN ?", roleIds).
        Pluck("p.token", &permissions).Error
    
    if err != nil {
        return nil, err
    }
    
    // Load user-specific permissions
    var userPermissions []string
    orm.DB().
        Table("user_permissions up").
        Select("p.token").
        Joins("JOIN permissions p ON p.id = up.permission_id").
        Where("up.user_id = ?", userId).
        Pluck("p.token", &userPermissions)
    
    // Merge permissions
    permissionSet := make(map[string]bool)
    for _, p := range permissions {
        permissionSet[p] = true
    }
    for _, p := range userPermissions {
        permissionSet[p] = true
    }
    
    result := make([]string, 0, len(permissionSet))
    for p := range permissionSet {
        result = append(result, p)
    }
    
    return result, nil
}

权限缓存

配置权限缓存

yaml
# config.yaml
auth:
  permission:
    cacheEnabled: true
    cacheTTL: 300 # seconds

清除权限缓存

go
import "github.com/ilxqx/vef-framework-go/auth"

// Clear cache for specific user
auth.ClearPermissionCache(userId)

// Clear all permission cache
auth.ClearAllPermissionCache()

动态权限

基于条件的权限

go
func (r *OrderResource) ApproveOrder(ctx fiber.Ctx, params struct {
    OrderId string `json:"orderId" validate:"required"`
}) error {
    currentUser := contextx.GetCurrentUser(ctx)
    
    // Load order
    var order models.Order
    if err := orm.DB().First(&order, "id = ?", params.OrderId).Error; err != nil {
        return api.NotFound(ctx, "Order not found")
    }
    
    // Check dynamic permission based on order amount
    if order.Amount > 10000 {
        if !currentUser.HasPermission("order:approve:high") {
            return api.Forbidden(ctx, "Cannot approve high-value orders")
        }
    } else {
        if !currentUser.HasPermission("order:approve") {
            return api.Forbidden(ctx, "Permission denied")
        }
    }
    
    // Approve order
    order.Status = "approved"
    order.ApprovedBy = currentUser.Id
    order.ApprovedAt = time.Now()
    
    if err := orm.DB().Save(&order).Error; err != nil {
        return api.Error(ctx, "Failed to approve order")
    }
    
    return api.Success(ctx, order)
}

权限继承

实现权限继承

go
// Permission hierarchy
// admin:* -> admin:user:*, admin:order:*, admin:system:*
// admin:user:* -> admin:user:read, admin:user:create, admin:user:update, admin:user:delete

func (u *UserInfo) HasPermission(permission string) bool {
    // Check exact match
    for _, p := range u.Permissions {
        if p == permission {
            return true
        }
    }
    
    // Check wildcard permissions
    parts := strings.Split(permission, ":")
    for i := len(parts) - 1; i >= 0; i-- {
        wildcardPermission := strings.Join(parts[:i], ":") + ":*"
        for _, p := range u.Permissions {
            if p == wildcardPermission {
                return true
            }
        }
    }
    
    return false
}

下一步

基于 Apache License 2.0 许可发布