如何在ASP.NET Core中同时使用JWT Bearer与自定义认证方法
当然可以!ASP.NET Core的认证系统天生支持同时配置多种认证方案,刚好能完美匹配你「默认用JWT Bearer认证,仅少数场景用自定义认证头」的需求。下面我会一步步带你实现这个配置:
1. 配置多种认证方案
首先在Program.cs里,我们需要同时注册JWT Bearer认证和自定义认证方案。先设置默认认证为JWT,这样大部分接口不用额外配置就会自动使用JWT验证:
builder.Services.AddAuthentication(options => { // 设置默认的认证和挑战方案为JWT Bearer options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) // 注册JWT Bearer认证,这里按你常规的JWT配置来就行 .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = builder.Configuration["Jwt:Issuer"], ValidAudience = builder.Configuration["Jwt:Audience"], IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"])) }; }) // 注册自定义认证方案,这里给它起个名字比如"CustomHeaderAuth" .AddScheme<AuthenticationSchemeOptions, CustomHeaderAuthenticationHandler>("CustomHeaderAuth", options => { });
2. 实现自定义认证处理器
接下来需要写一个自定义的认证处理器,用来解析和验证你的自定义认证头。这个处理器要继承AuthenticationHandler<AuthenticationSchemeOptions>,并实现核心的认证逻辑:
public class CustomHeaderAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions> { public CustomHeaderAuthenticationHandler(IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { } protected override async Task<AuthenticateResult> HandleAuthenticateAsync() { // 从请求头中获取自定义的认证字段,比如这里假设是"X-Custom-Token" if (!Request.Headers.TryGetValue("X-Custom-Token", out var customTokenHeader)) { return AuthenticateResult.Fail("自定义认证头不存在"); } var customToken = customTokenHeader.ToString(); // 这里替换成你实际的自定义认证逻辑——比如验证token的有效性、查询用户信息等 bool isTokenValid = ValidateCustomToken(customToken); if (!isTokenValid) { return AuthenticateResult.Fail("自定义认证头无效"); } // 认证通过后,创建用户身份凭证 var claims = new[] { new Claim(ClaimTypes.NameIdentifier, "custom-user-id"), new Claim(ClaimTypes.Name, "CustomUser") }; var identity = new ClaimsIdentity(claims, Scheme.Name); var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, Scheme.Name); return AuthenticateResult.Success(ticket); } // 示例:自定义token验证逻辑,你可以根据业务需求修改 private bool ValidateCustomToken(string token) { // 这里只是简单示例,实际场景可能要查数据库、调用验证接口等 return token == "YourValidCustomToken123"; } }
3. 给接口指定认证方案
- 默认接口:直接用
[Authorize]特性即可,因为我们已经把JWT设为默认方案,这些接口会自动走JWT认证。 - 需要自定义认证的接口:在
[Authorize]特性里指定我们刚才注册的自定义方案名称:
// 默认JWT认证的接口 [ApiController] [Route("api/default")] [Authorize] public class DefaultController : ControllerBase { [HttpGet] public IActionResult GetDefaultData() { return Ok("此接口仅允许JWT认证通过的用户访问"); } } // 使用自定义认证头的接口 [ApiController] [Route("api/custom")] [Authorize(AuthenticationSchemes = "CustomHeaderAuth")] public class CustomAuthController : ControllerBase { [HttpGet] public IActionResult GetCustomData() { return Ok("此接口仅允许携带有效自定义认证头的请求访问"); } }
4. 注意中间件顺序
最后别忘了在Program.cs里按正确顺序添加中间件——认证中间件必须在授权中间件之前:
app.UseAuthentication(); app.UseAuthorization();
额外小技巧
如果某个接口需要支持两种认证方式都能访问(比如既可以用JWT,也可以用自定义头),只需要把多个方案用逗号分隔即可:
[Authorize(AuthenticationSchemes = $"{JwtBearerDefaults.AuthenticationScheme},CustomHeaderAuth")]
这样请求只要满足其中一种认证方式,就能成功访问接口。
内容的提问来源于stack exchange,提问作者David Derman
相关产品推荐
相关产品推荐

