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

.NET 6 Web API兼容IdentityServer与自定义JWT认证并逐步替换方案咨询

实现.NET 6 Web API同时支持IdentityServer与自定义JWT双认证

问题背景

现有.NET 6 Web API长期使用IdentityServer认证,需新增自定义JWT认证方式:客户端通过请求头auth-method: jwt指定使用自定义JWT,无该头时默认使用IdentityServer认证。已实现TokenService但不知如何接入并完成切换逻辑。

解决方案步骤

1. 注册双认证方案

修改ConfigureServices中的认证配置,同时注册IdentityServer和自定义JWT两种认证方案并命名区分:

private void ConfigureAuthentication(IServiceCollection services)
{
    services.AddAuthentication()
        // IdentityServer认证方案,命名为"IdentityServerBearer"
        .AddIdentityServerAuthentication("IdentityServerBearer", options =>
        {
            options.Authority = Config.IdentityServerBaseUri;
            options.RequireHttpsMetadata = false;
            options.ApiName = Config.AppApiName;
            options.ApiSecret = Config.ClientSecret;
        })
        // 自定义JWT认证方案,命名为"CustomJwt"
        .AddJwtBearer("CustomJwt", options =>
        {
            options.TokenValidationParameters = new TokenValidationParameters
            {
                ValidateIssuer = true,
                ValidIssuer = Config.CustomJwtIssuer, // 与自定义JWT签发的发行人一致
                ValidateAudience = true,
                ValidAudience = Config.CustomJwtAudience, // 与自定义JWT签发的受众一致
                ValidateIssuerSigningKey = true,
                IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Config.CustomJwtSecret)), // 自定义JWT的签名密钥
                ValidateLifetime = true
            };

            // 可选:通过TokenService做额外验证
            options.Events = new JwtBearerEvents
            {
                OnTokenValidated = context =>
                {
                    var tokenService = context.HttpContext.RequestServices.GetRequiredService<ITokenService>();
                    // 可调用tokenService.DecodeJwt()做自定义校验逻辑
                    return Task.CompletedTask;
                }
            };
        });

    // 配置默认授权策略,支持两种认证方案
    services.AddAuthorization(options =>
    {
        options.DefaultPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .AddAuthenticationSchemes("IdentityServerBearer", "CustomJwt")
            .Build();
    });
}

2. 实现请求头驱动的认证方案切换

通过自定义IAuthenticationSchemeProvider实现基于请求头的方案选择:
首先注册自定义Provider:

services.AddSingleton<IAuthenticationSchemeProvider, CustomAuthenticationSchemeProvider>();

然后实现该Provider:

public class CustomAuthenticationSchemeProvider : AuthenticationSchemeProvider
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public CustomAuthenticationSchemeProvider(IOptions<AuthenticationOptions> options, IHttpContextAccessor httpContextAccessor) 
        : base(options)
    {
        _httpContextAccessor = httpContextAccessor;
    }

    public override async Task<AuthenticationScheme?> GetDefaultAuthenticateSchemeAsync()
    {
        var context = _httpContextAccessor.HttpContext;
        if (context != null)
        {
            // 检查请求头,指定auth-method为jwt时使用自定义JWT方案
            if (context.Request.Headers.TryGetValue("auth-method", out var authMethod) && 
                authMethod.Equals("jwt", StringComparison.OrdinalIgnoreCase))
            {
                return await GetSchemeAsync("CustomJwt");
            }
        }
        // 默认使用IdentityServer方案
        return await GetSchemeAsync("IdentityServerBearer");
    }
}

3. 保留原有控制器逻辑

无需修改现有AccountController的[Authorize]属性,默认授权策略已支持两种认证方式:

[HttpGet]
[Authorize]
[CustomClaimFilter]        
public IActionResult Get()
{
    // 两种认证方式都会正确填充Claims,可直接获取用户信息返回
}

关键注意事项

  • 确保自定义JWT的TokenValidationParameters与TokenService.GetJwt()的签发参数完全匹配
  • 若需统一两种认证方式的Claims格式,可在各自的OnTokenValidated事件中添加Claims转换逻辑
  • 测试时需分别验证两种场景:不带auth-method头用IdentityServer Token,带auth-method: jwt头用自定义JWT

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 11:20:21