ASP.NET Core API对接外部身份服务的最佳认证方案咨询
自定义外部身份服务对接ASP.NET Core API的最佳认证实践
当前实现方案
你目前通过自定义顶级中间件实现认证逻辑,每个请求都会调用身份服务API验证Token,具体代码如下:
数据API的自定义认证中间件
public class CustomAuthMiddleware { private readonly RequestDelegate _next; private readonly ILogger _logger; private readonly IAuthenticationService _authenticationService; public CustomAuthMiddleware(RequestDelegate next, ILoggerFactory logFactory, IAuthenticationService authenticationService) { _next = next; _logger = logFactory.CreateLogger<CustomAuthMiddleware>(); _authenticationService = authenticationService; } public async Task Invoke(HttpContext context) { string token = context.Request.Headers["ApiToken"]; if (!string.IsNullOrEmpty(token)) { // 调用身份服务API验证Token var isVerified = await _authenticationService.VerifyToken(token); if (isVerified) await _next(context); } throw new AppException(System.Net.HttpStatusCode.NotFound); } }
身份服务的Token验证接口
[Authorize] [HttpGet("verifyToken")] public async Task<IActionResult> verifyToken() { var user = await _userManager.FindByEmailAsync(User.FindFirstValue(ClaimTypes.Email)); if (user != null) return Ok(); return BadRequest(); }
该方案可正常运行,但存在性能损耗(每次请求都需调用身份服务)、未集成ASP.NET Core原生认证体系的问题,以下是更符合最佳实践的优化方案:
推荐的优化方案
1. JWT本地验证(无中心化调用,性能最优)
如果身份服务颁发的是JWT令牌,可直接在数据API本地完成验证,无需每次请求身份服务:
- 身份服务采用非对称加密算法(如RS256)生成JWT,将公钥提供给数据API,私钥由身份服务保管
- 数据API配置JWT认证中间件,用公钥验证令牌的签名、过期时间、受众等信息
- 验证通过后,令牌中的Claims会自动填充到
HttpContext.User,可直接用[Authorize]属性控制接口访问
配置示例:
// Program.cs中配置认证服务 builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddJwtBearer(options => { options.TokenValidationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidIssuer = "你的身份服务域名", ValidateAudience = true, ValidAudience = "数据API的受众标识", ValidateLifetime = true, IssuerSigningKey = new JsonWebKey("身份服务公开的公钥"), ValidateIssuerSigningKey = true }; }); // 启用认证、授权中间件(注意顺序:先认证后授权) app.UseAuthentication(); app.UseAuthorization();
之后只需在需要认证的接口上添加[Authorize]属性即可,无需自定义中间件。
2. OAuth 2.0 Token Introspection(中心化验证,符合标准协议)
如果需要支持令牌提前吊销等场景,必须保持中心化验证,可使用OAuth 2.0的Token Introspection规范(RFC 7662):
- 身份服务实现标准的Introspection端点,数据API向该端点发送Token获取验证结果
- 使用
IdentityModel.AspNetCore库集成Introspection中间件,替代自定义中间件,自带缓存机制可减少身份服务压力
配置示例:
// Program.cs中配置认证服务 builder.Services.AddAuthentication(OAuth2IntrospectionDefaults.AuthenticationScheme) .AddOAuth2Introspection(options => { options.Authority = "你的身份服务域名"; options.ClientId = "数据API的客户端ID"; options.ClientSecret = "数据API的客户端密钥"; // 配置验证结果缓存时长,避免重复调用 options.CacheDuration = TimeSpan.FromMinutes(5); }); app.UseAuthentication(); app.UseAuthorization();
现有方案的最小改进(若需保留自定义逻辑)
如果因特殊原因必须保留自定义验证逻辑,建议:
- 认证失败时返回
401 Unauthorized而非404 NotFound,设置context.Response.StatusCode = StatusCodes.Status401Unauthorized并返回标准错误响应 - 添加Token验证结果缓存,短期缓存已验证的Token,减少重复调用身份服务
- 实现
IAuthenticationHandler集成到ASP.NET Core认证体系,而非使用顶级自定义中间件,这样可配合[Authorize]属性使用
内容的提问来源于stack exchange,提问作者barak
相关产品推荐
相关产品推荐

