You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET 8中如何在运行时动态修改JWT认证方案

.NET 8 运行时动态修改JWT认证方案及受众(无需重启应用)

我正在开发一个.NET 8项目,使用ASP.NET Core内置的JWT认证机制,需要在运行时动态修改(更新、删除、新增)JWT认证方案及受众信息,且无需重启应用。当前的配置与代码如下:

当前配置(appsettings.json)

{
  "AuthRules": [
    {
      "Service": "scheme1",
      "Audiences": [ "aud1", "aud2" ]
    },
    {
      "Service": "Scheme2",
      "Audiences": [ "aud1", "aud2", "aud3" ]
    }
  ]
}

现有JWT认证配置代码

public static void AddAuthRules(WebApplicationBuilder builder)
{
    var signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("test"));

    foreach (var rule in AppConfig.getValues("AuthRules"))
    {
        List<string> audiences = new List<string>();

        foreach (KeyValuePair<string, string?> item in rule.GetSection("Audiences").AsEnumerable())
        {
            if (!string.IsNullOrEmpty(item.Value))
                audiences.Add(item.Value);
        }

        var tokenValidationParameters = new TokenValidationParameters
        {
            ValidateIssuerSigningKey = true,
            IssuerSigningKey = signingKey,
            ValidateIssuer = true,
            ValidIssuer = "issExample",
            ValidateAudience = true,
            ValidAudiences = audiences,
            ValidateLifetime = true,
            ClockSkew = TimeSpan.Zero,
            RequireExpirationTime = false
        };

        builder.Services.AddAuthentication()
         .AddJwtBearer(rule.GetSection("Service").Value!, x =>
         {
             x.Events = new JwtBearerEvents
             {
                 OnTokenValidated = context =>
                 {
                     // 添加令牌验证成功的自定义逻辑
                     return Task.CompletedTask;
                 },
                 OnAuthenticationFailed = context =>
                 {
                     // 添加认证失败的自定义逻辑
                     return Task.CompletedTask;
                 }
             };

             x.RequireHttpsMetadata = false;
             x.TokenValidationParameters = tokenValidationParameters;
         });
    }
}

动态修改实现方案

现有代码在启动时一次性注册所有JWT认证方案,无法支持运行时动态变更。要实现需求,需通过配置动态加载、认证方案缓存管理来实现:

1. 启用配置实时刷新

确保appsettings.json支持自动刷新,在构建WebApplicationBuilder时添加配置:

builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

2. 实现认证规则管理器

创建单例托管服务,负责监听配置变化、动态更新认证方案:

public class AuthRuleManager : IHostedService, IDisposable
{
    private readonly IConfiguration _configuration;
    private readonly IAuthenticationSchemeProvider _schemeProvider;
    private readonly IOptionsMonitorCache<JwtBearerOptions> _jwtOptionsCache;
    private IDisposable? _changeToken;
    private readonly SymmetricSecurityKey _signingKey;

    public AuthRuleManager(IConfiguration configuration, 
        IAuthenticationSchemeProvider schemeProvider,
        IOptionsMonitorCache<JwtBearerOptions> jwtOptionsCache)
    {
        _configuration = configuration;
        _schemeProvider = schemeProvider;
        _jwtOptionsCache = jwtOptionsCache;
        _signingKey = new SymmetricSecurityKey(Encoding.ASCII.GetBytes("test"));
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        // 初始加载认证规则
        LoadAuthRules();
        // 监听配置变化
        RegisterConfigChangeCallback();
        return Task.CompletedTask;
    }

    private void RegisterConfigChangeCallback()
    {
        _changeToken?.Dispose();
        _changeToken = _configuration.GetReloadToken().RegisterChangeCallback(_ =>
        {
            LoadAuthRules();
            RegisterConfigChangeCallback();
        }, null);
    }

    private void LoadAuthRules()
    {
        var authRules = _configuration.GetSection("AuthRules").Get<List<AuthRule>>() ?? new List<AuthRule>();
        
        // 获取当前所有JWT认证方案
        var existingSchemes = _schemeProvider.GetAllSchemesAsync().Result
            .Where(s => s.HandlerType == typeof(JwtBearerHandler))
            .Select(s => s.Name)
            .ToList();

        // 移除已删除的认证方案
        foreach (var schemeName in existingSchemes.Except(authRules.Select(r => r.Service)))
        {
            _schemeProvider.RemoveSchemeAsync(schemeName).Wait();
            _jwtOptionsCache.TryRemove(schemeName);
        }

        // 更新或新增认证方案
        foreach (var rule in authRules)
        {
            var tokenValidationParams = new TokenValidationParameters
            {
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = _signingKey,
                ValidateIssuer = true,
                ValidIssuer = "issExample",
                ValidateAudience = true,
                ValidAudiences = rule.Audiences,
                ValidateLifetime = true,
                ClockSkew = TimeSpan.Zero,
                RequireExpirationTime = false
            };

            // 创建JWT选项配置
            var jwtOptions = new JwtBearerOptions
            {
                Events = new JwtBearerEvents
                {
                    OnTokenValidated = context =>
                    {
                        // 令牌验证成功的自定义逻辑
                        return Task.CompletedTask;
                    },
                    OnAuthenticationFailed = context =>
                    {
                        // 认证失败的自定义逻辑
                        return Task.CompletedTask;
                    }
                },
                RequireHttpsMetadata = false,
                TokenValidationParameters = tokenValidationParams
            };

            // 移除旧配置(若存在)
            _jwtOptionsCache.TryRemove(rule.Service);
            // 添加新配置到缓存
            _jwtOptionsCache.TryAdd(rule.Service, jwtOptions);

            // 若方案不存在则添加
            if (!existingSchemes.Contains(rule.Service))
            {
                _schemeProvider.AddSchemeAsync(new AuthenticationScheme(rule.Service, rule.Service, typeof(JwtBearerHandler))).Wait();
            }
        }
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _changeToken?.Dispose();
        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _changeToken?.Dispose();
    }
}

// 用于绑定配置的模型类
public class AuthRule
{
    public string Service { get; set; } = string.Empty;
    public List<string> Audiences { get; set; } = new List<string>();
}

3. 调整Program.cs中的服务注册

移除原有的AddAuthRules调用,改为注册认证基础服务和规则管理器:

var builder = WebApplication.CreateBuilder(args);

// 启用appsettings实时刷新
builder.Configuration.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true);

// 注册认证核心服务
builder.Services.AddAuthentication();

// 注册认证规则管理器(托管服务)
builder.Services.AddSingleton<AuthRuleManager>();
builder.Services.AddHostedService(sp => sp.GetRequiredService<AuthRuleManager>());

// 其他服务注册...

var app = builder.Build();

// 启用认证中间件
app.UseAuthentication();
app.UseAuthorization();

// 其他中间件配置...

app.Run();

关键说明

  • 配置刷新:通过reloadOnChange: true监听appsettings文件变化,配置更新后自动触发认证规则重新加载
  • 方案管理:通过IAuthenticationSchemeProvider添加/移除认证方案,通过IOptionsMonitorCache<JwtBearerOptions>更新JWT配置
  • 即时生效:所有新的认证请求会立即使用更新后的配置,无需重启应用
  • 生产环境建议:示例中的固定签名密钥需替换为安全的密钥管理方案(如Azure Key Vault),配置源可替换为数据库或配置中心以提升实时性

内容的提问来源于stack exchange,提问作者Zahidli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 17:27:04