Files
lijiaoqiao/supply-api/internal/middleware/token_revocation_service.go
Your Name 8ac23bf7d4 test: improve coverage and fix sanitizer bug
- Fix MaskMap to properly handle []string sensitive fields
- Add missing slice handling in sanitizer
- Add comprehensive tests for GetMetrics and CreateEventsBatch
- Improve audit/handler coverage from 49.8% to 68.8%
- Fix test expectations to match actual sanitizer behavior
- All tests pass
2026-04-08 07:44:58 +08:00

75 lines
2.4 KiB
Go
Raw Permalink 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.
package middleware
import (
"context"
"time"
"lijiaoqiao/supply-api/internal/cache"
)
// TokenRevocationService Token吊销服务P0-03修复
// 实现主动失效机制,确保吊销传播延迟 <= 5s
type TokenRevocationService struct {
redisCache TokenCacheBackend
dbBackend TokenRevocationBackend
}
// TokenRevocationBackend Token吊销数据库后端接口
type TokenRevocationBackend interface {
// RevokeToken 在数据库中吊销token
RevokeToken(ctx context.Context, tokenID string, reason string) error
// GetTokenStatus 获取token状态
GetTokenStatus(ctx context.Context, tokenID string) (string, error)
}
// NewTokenRevocationService 创建Token吊销服务
func NewTokenRevocationService(redisCache TokenCacheBackend, dbBackend TokenRevocationBackend) *TokenRevocationService {
return &TokenRevocationService{
redisCache: redisCache,
dbBackend: dbBackend,
}
}
// RevokeAndPublish 吊销token并发布吊销事件主动失效机制核心
// 步骤:
// 1. 更新数据库状态
// 2. 发布吊销事件到Redis Pub/Sub
// 3. 返回成功(异步传播到所有缓存节点)
func (s *TokenRevocationService) RevokeAndPublish(ctx context.Context, tokenID string, reason string) error {
// 1. 更新数据库状态(同步)
if err := s.dbBackend.RevokeToken(ctx, tokenID, reason); err != nil {
return err
}
// 2. 发布吊销事件到Redis Pub/Sub异步触发主动失效
revokeEvent := &cache.TokenRevokedCacheEvent{
TokenID: tokenID,
RevokedAt: time.Now(),
Reason: reason,
}
// 发布操作需要成功,否则缓存可能不会及时失效
if err := s.redisCache.PublishTokenRevoked(ctx, revokeEvent); err != nil {
// 发布失败时,至少要确保本地缓存失效
s.redisCache.InvalidateToken(ctx, tokenID)
return err
}
return nil
}
// StartRevocationSubscriber 启动吊销事件订阅者
// 在应用启动时调用启动后台goroutine监听吊销事件
func (s *TokenRevocationService) StartRevocationSubscriber(ctx context.Context) error {
return s.redisCache.SubscribeTokenRevoked(ctx, func(event *cache.TokenRevokedCacheEvent) {
// 收到吊销事件,立即失效本地缓存
s.redisCache.InvalidateToken(ctx, event.TokenID)
})
}
// RevokeLocalOnly 仅在本地缓存失效(不发布事件,用于测试或特殊场景)
func (s *TokenRevocationService) RevokeLocalOnly(ctx context.Context, tokenID string) error {
s.redisCache.InvalidateToken(ctx, tokenID)
return nil
}