Sub2API v1.0 - AI API 网关(二开初始版本,基于上游 Wei-Shaw/sub2api)
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
Release / update-version (push) Has been cancelled
Release / build-frontend (push) Has been cancelled
Release / release (push) Has been cancelled
Release / sync-version-file (push) Has been cancelled
CI / shell (push) Canceled after 0s
CI / test (push) Canceled after 0s
CI / frontend (push) Canceled after 0s
CI / golangci-lint (push) Canceled after 0s
Security Scan / backend-security (push) Canceled after 0s
Security Scan / frontend-security (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"time"
|
||||
|
||||
"github.com/Wei-Shaw/sub2api/internal/pkg/logger"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// CyberSessionBlockStore 是 cyber 会话屏蔽表的存取接口。
|
||||
// repository 层 gatewayCache 附带实现(类型断言探测接入,不改 GatewayCache
|
||||
// 共享接口);测试 stub 不实现时屏蔽能力自动降级关闭。
|
||||
type CyberSessionBlockStore interface {
|
||||
SetCyberSessionBlocked(ctx context.Context, key string, ttl time.Duration) error
|
||||
IsCyberSessionBlocked(ctx context.Context, key string) (bool, error)
|
||||
}
|
||||
|
||||
// CyberSessionBlockKey 派生会话屏蔽 key:仅用显式会话标识(header
|
||||
// session_id/conversation_id 或 body prompt_cache_key),混入 apiKeyID 隔离后
|
||||
// sha256。无显式标识返回空串——调用方必须放行(粒度决策:不退化到
|
||||
// user/apikey/内容派生)。
|
||||
func CyberSessionBlockKey(apiKeyID int64, c *gin.Context, body []byte) string {
|
||||
raw := explicitOpenAISessionID(c, body)
|
||||
if raw == "" {
|
||||
return ""
|
||||
}
|
||||
isolated := isolateOpenAISessionID(apiKeyID, raw)
|
||||
sum := sha256.Sum256([]byte(isolated))
|
||||
return hex.EncodeToString(sum[:])
|
||||
}
|
||||
|
||||
// cyberSessionBlockStore 探测 cache 是否具备屏蔽存储能力。
|
||||
// 注意:若未来以装饰器包装 GatewayCache(如日志/指标装饰器),该装饰器必须同时实现
|
||||
// CyberSessionBlockStore,否则会话屏蔽能力将静默降级关闭
|
||||
// (编译断言 var _ service.CyberSessionBlockStore = (*gatewayCache)(nil) 只覆盖
|
||||
// *gatewayCache 本体,无法覆盖其外层包装)。
|
||||
func (s *OpenAIGatewayService) cyberSessionBlockStore() CyberSessionBlockStore {
|
||||
if s == nil || s.cache == nil {
|
||||
return nil
|
||||
}
|
||||
store, ok := s.cache.(CyberSessionBlockStore)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return store
|
||||
}
|
||||
|
||||
// CyberSessionBlockRuntime 返回 (开关, TTL)。开关默认关。
|
||||
// 委托给 SettingService.GetCyberSessionBlockRuntime,进程内缓存避免热路径 DB 往返。
|
||||
func (s *OpenAIGatewayService) CyberSessionBlockRuntime(ctx context.Context) (bool, time.Duration) {
|
||||
if s == nil || s.settingService == nil {
|
||||
return false, time.Hour
|
||||
}
|
||||
return s.settingService.GetCyberSessionBlockRuntime(ctx)
|
||||
}
|
||||
|
||||
// MarkCyberSessionBlocked 把会话写入屏蔽表(写入点:cyber 命中后)。
|
||||
// 开关关闭、key 为空或存储不可用时静默跳过。
|
||||
func (s *OpenAIGatewayService) MarkCyberSessionBlocked(ctx context.Context, key string) {
|
||||
if key == "" {
|
||||
return
|
||||
}
|
||||
enabled, ttl := s.CyberSessionBlockRuntime(ctx)
|
||||
if !enabled {
|
||||
return
|
||||
}
|
||||
store := s.cyberSessionBlockStore()
|
||||
if store == nil {
|
||||
return
|
||||
}
|
||||
if err := store.SetCyberSessionBlocked(ctx, key, ttl); err != nil {
|
||||
logger.LegacyPrintf("service.openai_gateway", "cyber session block write failed: err=%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// IsCyberSessionBlocked 查询会话是否被屏蔽(拦截点)。开关关闭、key 为空、
|
||||
// 存储不可用或查询出错时返回 false(fail-open:屏蔽是增强防护,不阻断主链路)。
|
||||
func (s *OpenAIGatewayService) IsCyberSessionBlocked(ctx context.Context, key string) bool {
|
||||
if key == "" {
|
||||
return false
|
||||
}
|
||||
enabled, _ := s.CyberSessionBlockRuntime(ctx)
|
||||
if !enabled {
|
||||
return false
|
||||
}
|
||||
store := s.cyberSessionBlockStore()
|
||||
if store == nil {
|
||||
return false
|
||||
}
|
||||
blocked, err := store.IsCyberSessionBlocked(ctx, key)
|
||||
if err != nil {
|
||||
logger.LegacyPrintf("service.openai_gateway", "cyber session block read failed: err=%v", err)
|
||||
return false
|
||||
}
|
||||
return blocked
|
||||
}
|
||||
Reference in New Issue
Block a user