.NET Minimal APIs如何实现API密钥全局校验避免重复验证代码
解决方案
你可以通过以下三种常用方式实现API-KEY校验逻辑复用,避免每个接口重复编写代码:
方案1:端点过滤器(推荐,.NET 7及以上版本适用)
这是Minimal API原生提供的扩展能力,支持单接口或批量接口统一挂载逻辑:
- 首先定义校验过滤器
public class ApiKeyValidationFilter : IEndpointFilter { // 注入你的ApiKey校验服务、数据库上下文等依赖 private readonly IApiKeyValidationService _validationService; public ApiKeyValidationFilter(IApiKeyValidationService validationService) { _validationService = validationService; } public async ValueTask<object?> InvokeAsync(EndpointFilterInvocationContext context, EndpointFilterDelegate next) { // 直接从当前请求上下文获取API-KEY头 if (!context.HttpContext.Request.Headers.TryGetValue("API-KEY", out var apiToken) || string.IsNullOrWhiteSpace(apiToken)) { return Results.Unauthorized(); } // 执行你的校验逻辑:比对数据库值、判断过期时间等 if (!_validationService.Validate(apiToken)) { return Results.Unauthorized(); } // 校验通过则继续执行接口业务逻辑 return await next(context); } }
- 给需要校验的接口挂载过滤器即可
// 单个接口单独挂载 app.MapGet("/getCustomers", () => { // 无需再写校验逻辑,直接写业务代码 return Database.Customers.ToList(); }).AddEndpointFilter<ApiKeyValidationFilter>(); // 批量接口统一挂载:用路由组统一配置,组下所有接口自动带校验 var needAuthApiGroup = app.MapGroup("/api") .AddEndpointFilter<ApiKeyValidationFilter>(); needAuthApiGroup.MapGet("/getCustomers", () => Database.Customers.ToList()); needAuthApiGroup.MapPost("/addCustomer", (Customer customer) => { /* 业务逻辑 */ });
方案2:自定义授权策略(全.NET版本适用)
基于ASP.NET Core原生授权体系实现,兼容性最强:
- 定义ApiKey认证处理器
public class ApiKeyAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions> { private readonly IApiKeyValidationService _validationService; public ApiKeyAuthenticationHandler( IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock, IApiKeyValidationService validationService) : base(options, logger, encoder, clock) { _validationService = validationService; } protected override async Task<AuthenticateResult> HandleAuthenticateAsync() { if (!Request.Headers.TryGetValue("API-KEY", out var apiToken) || string.IsNullOrWhiteSpace(apiToken)) { return AuthenticateResult.Fail("缺失API-KEY请求头"); } if (!_validationService.Validate(apiToken)) { return AuthenticateResult.Fail("无效的API-KEY"); } // 校验通过后可将用户信息存入Claims,后续接口中可直接读取 var claims = new[] { new Claim(ClaimTypes.Name, "ApiUser") }; var identity = new ClaimsIdentity(claims, Scheme.Name); var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, Scheme.Name); return AuthenticateResult.Success(ticket); } }
- 注册服务与中间件
// Program.cs 中注册服务 builder.Services.AddScoped<IApiKeyValidationService, ApiKeyValidationService>(); builder.Services.AddAuthentication("ApiKey") .AddScheme<AuthenticationSchemeOptions, ApiKeyAuthenticationHandler>("ApiKey", _ => { }); builder.Services.AddAuthorization(); // 中间件管道添加配置,注意顺序要放在路由之后、端点之前 app.UseAuthentication(); app.UseAuthorization();
- 给需要校验的接口开启授权即可
// 单个接口开启授权 app.MapGet("/getCustomers", [Authorize] () => { return Database.Customers.ToList(); }); // 路由组统一开启授权 var needAuthApiGroup = app.MapGroup("/api").RequireAuthorization(); needAuthApiGroup.MapGet("/getCustomers", () => Database.Customers.ToList());
方案3:自定义注入类实现(符合你最初的思路)
如果你希望用自己定义的RequiresApiTokenKey类实现,只需要注入IHttpContextAccessor即可获取当前请求上下文:
- 注册HttpContext访问器
builder.Services.AddHttpContextAccessor();
- 改造你的自定义类
public class RequiresApiTokenKey { public bool IsValid { get; } public RequiresApiTokenKey(IHttpContextAccessor httpContextAccessor, IApiKeyValidationService validationService) { var httpContext = httpContextAccessor.HttpContext; if (httpContext == null) { IsValid = false; return; } if (!httpContext.Request.Headers.TryGetValue("API-KEY", out var apiToken) || string.IsNullOrWhiteSpace(apiToken)) { IsValid = false; return; } IsValid = validationService.Validate(apiToken); } }
- 注册自定义类后即可在接口中注入使用
// 注册服务 builder.Services.AddTransient<RequiresApiTokenKey>(); // 接口中直接注入使用 app.MapGet("/getCustomers", (RequiresApiTokenKey apiKeyChecker) => { if (!apiKeyChecker.IsValid) return Results.Unauthorized(); return Database.Customers.ToList(); });
该方案仍需在每个接口中添加有效性判断,复用性不如前两种方案。
内容的提问来源于stack exchange,提问作者Tono Nam
相关产品推荐
相关产品推荐

