authzguard

package
v0.3.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 16, 2025 License: Apache-2.0 Imports: 8 Imported by: 0

README

AuthzGuard - PEP SDK

AuthzGuard 是一个轻量级的权限检查客户端(PEP - Policy Enforcement Point),为业务服务提供简单易用的权限检查 API。

特性

  • 简单易用: 提供直观的 API,快速集成到业务服务
  • 高性能: 内置版本缓存,减少不必要的查询
  • 实时更新: 通过 Redis 订阅策略变更,自动刷新缓存
  • 批量检查: 支持批量权限检查,提升性能
  • Gin 中间件: 开箱即用的 Gin 中间件,快速保护路由
  • 灵活配置: 支持自定义错误处理、路径跳过等

快速开始

1. 安装
go get github.com/FangcunMount/iam-contracts/pkg/authzguard
2. 创建 AuthzGuard 实例
import (
    "github.com/FangcunMount/iam-contracts/pkg/authzguard"
    casbin "github.com/casbin/casbin/v2"
)

// 创建 Casbin Enforcer
enforcer, _ := casbin.NewEnforcer("model.conf", "policy.csv")

// 创建 AuthzGuard
guard, err := authzguard.NewAuthzGuard(authzguard.Config{
    Enforcer:     enforcer,
    RedisClient:  redisClient, // 可选,用于监听策略变更
    CacheTTL:     5 * time.Minute,
    VersionTopic: "authz:policy_changed",
})
3. 基本权限检查
allowed, err := guard.CheckPermission(
    ctx,
    "user123",    // 用户ID
    "tenant1",    // 租户ID
    "order",      // 资源
    "read",       // 操作
)

if allowed {
    // 执行业务逻辑
} else {
    // 拒绝访问
}
4. 批量权限检查
permissions := []authzguard.Permission{
    {Resource: "order", Action: "read"},
    {Resource: "order", Action: "write"},
    {Resource: "product", Action: "read"},
}

results, err := guard.BatchCheckPermissions(ctx, userID, tenantID, permissions)
// results: {"order:read": true, "order:write": false, "product:read": true}
5. 服务权限检查
// 检查服务是否有权限
allowed, err := guard.CheckServicePermission(
    ctx,
    "order-service", // 服务ID
    "tenant1",
    "inventory",
    "update",
)

Gin 中间件

基本使用
// 创建中间件
authMiddleware := authzguard.NewAuthMiddleware(authzguard.MiddlewareConfig{
    Guard: guard,
    GetUserID: func(c *gin.Context) string {
        return c.GetString("user_id") // 从 JWT 或 Session 中提取
    },
    GetTenantID: func(c *gin.Context) string {
        return c.GetHeader("X-Tenant-ID")
    },
    SkipPaths: []string{"/health", "/login"},
})

// 保护路由
router.GET("/orders", 
    authMiddleware.RequirePermission("order", "read"),
    orderHandler,
)
需要任意一个权限
router.GET("/orders/:id", 
    authMiddleware.RequireAnyPermission([]authzguard.Permission{
        {Resource: "order", Action: "read"},
        {Resource: "order", Action: "write"},
    }),
    orderDetailHandler,
)
需要所有权限
router.POST("/orders/:id/ship", 
    authMiddleware.RequireAllPermissions([]authzguard.Permission{
        {Resource: "order", Action: "write"},
        {Resource: "inventory", Action: "update"},
    }),
    shipOrderHandler,
)

资源显示名称

// 注册资源的友好显示名称
guard.RegisterResource("order", "订单")
guard.RegisterResource("product", "产品")
guard.RegisterResource("inventory", "库存")

// 在错误提示中会显示友好名称
// "没有权限访问 订单" 而不是 "没有权限访问 order"

自定义错误处理

authMiddleware := authzguard.NewAuthMiddleware(authzguard.MiddlewareConfig{
    Guard: guard,
    GetUserID: getUserID,
    GetTenantID: getTenantID,
    ErrorHandler: func(c *gin.Context, err error) {
        // 自定义错误响应
        if permErr, ok := err.(*authzguard.PermissionError); ok {
            c.JSON(http.StatusForbidden, gin.H{
                "code": permErr.Code,
                "message": permErr.Message,
                "timestamp": time.Now().Unix(),
            })
            return
        }
        c.JSON(http.StatusInternalServerError, gin.H{
            "error": err.Error(),
        })
    },
})

缓存管理

// 获取缓存的版本号
version, exists := guard.GetCachedVersion(tenantID)

// 手动设置缓存版本
guard.SetCachedVersion(tenantID, newVersion)

// 缓存会自动刷新(通过 Redis 订阅)
// 当策略变更时,缓存会自动清空

架构说明

业务服务
    ↓
AuthzGuard (PEP SDK)
    ↓
Casbin Enforcer
    ↓
策略规则 (存储在数据库)

AuthzGuard 作为 PEP (Policy Enforcement Point),负责:

  1. 提供简单的权限检查 API
  2. 缓存策略版本,减少查询
  3. 监听策略变更,自动刷新
  4. 提供中间件,保护路由

最佳实践

1. 统一提取用户信息
// 创建通用的用户信息提取函数
func GetUserID(c *gin.Context) string {
    // 从 JWT Token 中提取
    claims := c.MustGet("claims").(*jwt.Claims)
    return claims.UserID
}

func GetTenantID(c *gin.Context) string {
    // 从请求头中提取
    return c.GetHeader("X-Tenant-ID")
}

// 在所有中间件中复用
authMiddleware := authzguard.NewAuthMiddleware(authzguard.MiddlewareConfig{
    Guard: guard,
    GetUserID: GetUserID,
    GetTenantID: GetTenantID,
})
2. 预先注册资源
// 在应用启动时注册所有资源
func registerResources(guard *authzguard.AuthzGuard) {
    guard.RegisterResource("order", "订单")
    guard.RegisterResource("product", "产品")
    guard.RegisterResource("user", "用户")
    guard.RegisterResource("inventory", "库存")
}
3. 分层权限检查
// 在 Controller 层使用中间件进行粗粒度检查
router.GET("/orders", authMiddleware.RequirePermission("order", "read"), ...)

// 在 Service 层进行细粒度检查
func (s *OrderService) GetOrder(ctx context.Context, userID, orderID string) {
    // 检查是否有权限访问特定订单
    order := s.repo.GetOrder(orderID)
    if order.UserID != userID {
        // 检查是否有管理员权限
        allowed, _ := s.guard.CheckPermission(ctx, userID, tenantID, "order", "admin")
        if !allowed {
            return ErrPermissionDenied
        }
    }
    // ...
}

性能建议

  1. 启用缓存: 配置合适的 CacheTTL,减少重复查询
  2. 使用批量检查: 对于多个权限检查,使用 BatchCheckPermissions
  3. 启用 Redis 订阅: 实时刷新缓存,保持策略最新
  4. 合理设置跳过路径: 对于公开路径(如健康检查),跳过权限检查

许可证

MIT

Documentation

Overview

Package authzguard 版本缓存

Package authzguard PEP SDK - 权限检查客户端 AuthzGuard 为业务服务提供简单易用的权限检查 API

Package authzguard 中间件

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExtractBearerToken

func ExtractBearerToken(c *gin.Context) string

ExtractBearerToken 从请求头中提取 Bearer Token

Types

type AuthMiddleware

type AuthMiddleware struct {
	// contains filtered or unexported fields
}

AuthMiddleware 认证中间件配置

func NewAuthMiddleware

func NewAuthMiddleware(config MiddlewareConfig) *AuthMiddleware

NewAuthMiddleware 创建认证中间件

func (*AuthMiddleware) RequireAllPermissions

func (m *AuthMiddleware) RequireAllPermissions(permissions []Permission) gin.HandlerFunc

RequireAllPermissions 要求所有权限的中间件

func (*AuthMiddleware) RequireAnyPermission

func (m *AuthMiddleware) RequireAnyPermission(permissions []Permission) gin.HandlerFunc

RequireAnyPermission 要求任意一个权限的中间件

func (*AuthMiddleware) RequirePermission

func (m *AuthMiddleware) RequirePermission(resource, action string) gin.HandlerFunc

RequirePermission 要求特定权限的中间件

用法:

router.GET("/users", authMiddleware.RequirePermission("user", "read"), handler)

type AuthzGuard

type AuthzGuard struct {
	// contains filtered or unexported fields
}

AuthzGuard 权限检查客户端

func NewAuthzGuard

func NewAuthzGuard(config Config) (*AuthzGuard, error)

NewAuthzGuard 创建 AuthzGuard 实例

func (*AuthzGuard) BatchCheckPermissions

func (g *AuthzGuard) BatchCheckPermissions(
	ctx context.Context,
	userID string,
	tenantID string,
	permissions []Permission,
) (map[string]bool, error)

BatchCheckPermissions 批量检查权限

参数:

  • ctx: 上下文
  • userID: 用户ID
  • tenantID: 租户ID
  • permissions: 权限检查列表 [{resource, action}, ...]

返回:

  • map[string]bool: 权限检查结果 {"resource:action": true/false}
  • error: 错误信息

func (*AuthzGuard) CheckPermission

func (g *AuthzGuard) CheckPermission(
	ctx context.Context,
	userID string,
	tenantID string,
	resource string,
	action string,
) (bool, error)

CheckPermission 检查用户是否有权限执行操作

参数:

  • ctx: 上下文
  • userID: 用户ID
  • tenantID: 租户ID
  • resource: 资源标识 (例如: "user", "order")
  • action: 操作 (例如: "read", "write", "delete")

返回:

  • bool: 是否有权限
  • error: 错误信息

func (*AuthzGuard) CheckServicePermission

func (g *AuthzGuard) CheckServicePermission(
	ctx context.Context,
	serviceID string,
	tenantID string,
	resource string,
	action string,
) (bool, error)

CheckServicePermission 检查服务是否有权限执行操作

参数:

  • ctx: 上下文
  • serviceID: 服务ID
  • tenantID: 租户ID
  • resource: 资源标识
  • action: 操作

func (*AuthzGuard) GetCachedVersion

func (g *AuthzGuard) GetCachedVersion(tenantID string) (int64, bool)

GetCachedVersion 获取缓存的版本号

func (*AuthzGuard) GetResourceDisplayName

func (g *AuthzGuard) GetResourceDisplayName(key string) string

GetResourceDisplayName 获取资源显示名称

func (*AuthzGuard) RegisterResource

func (g *AuthzGuard) RegisterResource(key string, displayName string)

RegisterResource 注册资源映射(用于友好的错误提示)

func (*AuthzGuard) SetCachedVersion

func (g *AuthzGuard) SetCachedVersion(tenantID string, version int64)

SetCachedVersion 设置缓存的版本号

type Config

type Config struct {
	Enforcer     Enforcer      // Casbin Enforcer
	RedisClient  *redis.Client // Redis 客户端(用于监听策略变更)
	CacheTTL     time.Duration // 缓存过期时间
	VersionTopic string        // 策略版本变更主题
}

Config AuthzGuard 配置

type Enforcer

type Enforcer interface {
	// Enforce 检查权限
	Enforce(sub, dom, obj, act string) (bool, error)
}

Enforcer Casbin Enforcer 接口

type MiddlewareConfig

type MiddlewareConfig struct {
	Guard        *AuthzGuard
	GetUserID    func(*gin.Context) string
	GetTenantID  func(*gin.Context) string
	ErrorHandler func(*gin.Context, error)
	SkipPaths    []string // 跳过认证的路径列表
}

MiddlewareConfig 中间件配置

type Permission

type Permission struct {
	Resource string // 资源
	Action   string // 操作
}

Permission 权限定义

type PermissionError

type PermissionError struct {
	Code    string
	Message string
	Details map[string]string
}

PermissionError 权限错误

func (*PermissionError) Error

func (e *PermissionError) Error() string

type VersionCache

type VersionCache struct {
	// contains filtered or unexported fields
}

VersionCache 策略版本缓存

func NewVersionCache

func NewVersionCache(ttl time.Duration) *VersionCache

NewVersionCache 创建版本缓存

func (*VersionCache) Clear

func (vc *VersionCache) Clear()

Clear 清空所有缓存

func (*VersionCache) Delete

func (vc *VersionCache) Delete(tenantID string)

Delete 删除指定租户的缓存

func (*VersionCache) Get

func (vc *VersionCache) Get(tenantID string) (int64, bool)

Get 获取缓存的版本号

func (*VersionCache) Set

func (vc *VersionCache) Set(tenantID string, version int64)

Set 设置缓存的版本号

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL