feat(identity): 实现统一认证运行时热切换

从 Active Revision 构造并验证 OIDC、BFF Session、Introspection 与 SSF Runtime,在数据库激活成功后原子替换内存引用。请求链路使用不可变快照,失败保留当前运行时,本地管理登录不受影响。\n\n验证:go test ./apps/api/...;go vet ./apps/api/...
This commit is contained in:
2026-07-17 12:05:00 +08:00
parent 96bbd3a2f6
commit a9e23cb237
14 changed files with 797 additions and 152 deletions
@@ -7,6 +7,7 @@ import (
"strings"
"github.com/easyai/easyai-ai-gateway/apps/api/internal/auth"
"github.com/easyai/easyai-ai-gateway/apps/api/internal/identity"
"github.com/easyai/easyai-ai-gateway/apps/api/internal/store"
)
@@ -52,17 +53,25 @@ func (s *Server) resolveGatewayUser(next http.Handler) http.Handler {
}
func (s *Server) resolveOIDCUserProjection(ctx context.Context, r *http.Request, user *auth.User) (store.ResolveOrProvisionOIDCUserResult, error) {
runtime := s.currentIdentityRuntime()
if runtime == nil {
return store.ResolveOrProvisionOIDCUserResult{}, errors.New("active identity runtime is unavailable")
}
return s.resolveOIDCUserProjectionForRevision(ctx, r, user, runtime.Revision)
}
func (s *Server) resolveOIDCUserProjectionForRevision(ctx context.Context, r *http.Request, user *auth.User, revision identity.Revision) (store.ResolveOrProvisionOIDCUserResult, error) {
if s.oidcUserResolver == nil {
return store.ResolveOrProvisionOIDCUserResult{}, errors.New("OIDC user resolver is unavailable")
}
return s.oidcUserResolver.ResolveOrProvisionOIDCUser(ctx, store.ResolveOrProvisionOIDCUserInput{
Issuer: s.cfg.OIDCIssuer,
Issuer: revision.Issuer,
Subject: user.ID,
Username: user.Username,
Roles: user.Roles,
TenantID: user.TenantID,
GatewayTenantKey: s.cfg.OIDCGatewayTenantKey,
ProvisioningEnabled: s.cfg.OIDCJITProvisioningEnabled,
GatewayTenantKey: revision.LocalTenantKey,
ProvisioningEnabled: revision.JITEnabled,
RequestIP: limitAuditText(requestIP(r), 128),
UserAgent: limitAuditText(r.UserAgent(), 512),
})