.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
相关产品推荐
相关产品推荐

