ASP.NET Core中x-api-key认证返回401的问题排查
问题诊断与修复方案
你的代码存在几个关键问题,导致API密钥获取为空且返回401,以下是具体修复步骤:
1. 修复ApiKeyAuthorizationAttribute的依赖注入问题
特性(Attribute)无法通过构造函数直接注入服务,你当前的_configuration字段始终为null,导致验证逻辑完全失效。需要从HttpContext的服务容器中获取IConfiguration:
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class)] public class ApiKeyAuthorizationAttribute : Attribute, IAuthorizationFilter { public void OnAuthorization(AuthorizationFilterContext context) { // 从请求服务容器中获取IConfiguration实例 var configuration = context.HttpContext.RequestServices.GetRequiredService<IConfiguration>(); var apiKey = context.HttpContext.Request.Headers["x-api-key"].FirstOrDefault(); if (string.IsNullOrEmpty(apiKey) || !IsApiKeyValid(apiKey, configuration)) { context.Result = new UnauthorizedResult(); } } private bool IsApiKeyValid(string apiKey, IConfiguration configuration) { var allowedApiKeys = configuration.GetSection("AllowedApiKeys").Get<string[]>(); // 处理配置为空的边界情况,避免空引用异常 return allowedApiKeys?.Contains(apiKey) ?? false; } }
2. 修复ApiKeyMiddleware的配置读取逻辑
你当前直接通过_configuration["AllowedApiKeys"]读取配置,如果AllowedApiKeys是数组格式,这个方法会返回null,导致验证条件永远不成立。需要改为读取数组配置:
public class ApiKeyMiddleware { private readonly RequestDelegate _next; private readonly IConfiguration _configuration; public ApiKeyMiddleware(RequestDelegate next, IConfiguration configuration) { _next = next; _configuration = configuration; } public async Task Invoke(HttpContext context) { var apiKey = context.Request.Headers["x-api-key"].FirstOrDefault(); var allowedApiKeys = _configuration.GetSection("AllowedApiKeys").Get<string[]>(); // 验证API密钥非空且在允许列表中 if (!string.IsNullOrEmpty(apiKey) && allowedApiKeys?.Contains(apiKey) == true) { await _next(context); } else { context.Response.StatusCode = StatusCodes.Status401Unauthorized; await context.Response.WriteAsync("Unauthorized"); } } }
3. 确认配置文件格式
确保appsettings.json中的AllowedApiKeys配置为数组格式(推荐使用):
{ "AllowedApiKeys": ["YourValidKey1", "YourValidKey2"] }
如果使用逗号分隔的字符串格式,需要修改配置读取逻辑:
// 在中间件或特性中替换为以下代码 var allowedApiKeys = _configuration["AllowedApiKeys"]?.Split(',', StringSplitOptions.RemoveEmptyEntries);
4. 避免重复验证逻辑
你同时实现了中间件和特性两种验证方式,建议二选一:
- 若需全局所有API强制验证:在
Program.cs中注册中间件,无需添加[ApiKeyAuthorization]特性app.UseMiddleware<ApiKeyMiddleware>(); - 若需部分API验证:仅使用
[ApiKeyAuthorization]特性,无需注册中间件
5. 调试建议
在验证逻辑中添加日志输出,确认API密钥和配置是否正确读取:
// 在中间件的Invoke方法中添加 var logger = context.RequestServices.GetRequiredService<ILogger<ApiKeyMiddleware>>(); logger.LogInformation("Received API Key: {ApiKey}", apiKey); logger.LogInformation("Allowed API Keys: {AllowedKeys}", allowedApiKeys != null ? string.Join(",", allowedApiKeys) : "None");
内容的提问来源于stack exchange,提问作者Peter_Griffindor
相关产品推荐
相关产品推荐

