You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于API Key的ASP.NET Core认证中自定义选项无法生效

问题

我有一个未启用安全机制的ASP.NET Core 3.1 Web API项目,需要通过基于API Key的认证方案保护它。核心逻辑是让客户端在请求头传入API Key,合法的API Key存储在appsettings.json中。

已完成的实现步骤如下:

  1. 自定义ApiKeyAuthenticationOptions类存储API Key:
public class ApiKeyAuthenticationOptions : AuthenticationSchemeOptions
{
    public const string DefaultScheme = "ApiKey";
    public string Scheme => DefaultScheme;
    public string AuthenticationType = DefaultScheme;
    public string MyConfigValue { get; set; }
}
  1. 在Startup的ConfigureServices中添加认证逻辑:
public void ConfigureServices(IServiceCollection services)
{
        services.AddSingleton(Configuration);
     services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
         .AddApiKeyAuthentication(Configuration);
     services.AddControllers();
}
  1. 定义AuthenticationBuilder的扩展方法AddApiKeyAuthentication:
public static AuthenticationBuilder AddApiKeyAuthentication(this AuthenticationBuilder builder, IConfiguration configuration)
{
    var config = configuration["MyConfigValue"];
    builder.Services.Configure<ApiKeyAuthenticationOptions>(options =>
    {
        options.MyConfigValue = config;
    });

    builder.AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>(ApiKeyAuthenticationOptions.DefaultScheme, options => { });

    return builder;
}
  1. 实现认证处理器ApiKeyAuthenticationHandler:
public class ApiKeyAuthenticationHandler : AuthenticationHandler<ApiKeyAuthenticationOptions>
{
    private const string ApiKeyName = "X-Api-Key";

    public ApiKeyAuthenticationHandler(IOptionsMonitor<ApiKeyAuthenticationOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock)
    {
    }

    protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
    {
        var myConfigValue = Options.MyConfigValue;

        if (!Request.Headers.ContainsKey(ApiKeyName))
        {
            return AuthenticateResult.Fail("Missing API Key");
        }

        var apiKey = Request.Headers[ApiKeyName];

        if (apiKey != myConfigValue)
        {
            return AuthenticateResult.Fail("Invalid API Key");
        }

        var claims = new[] { new Claim(ClaimTypes.NameIdentifier, "api-user") };
        var identity = new ClaimsIdentity(claims, Scheme.Name);
        var principal = new ClaimsPrincipal(identity);
        var ticket = new AuthenticationTicket(principal, Scheme.Name);

        return AuthenticateResult.Success(ticket);
    }
}

当前遇到的问题:

  • 构造函数中的options参数CurrentValue能正确读取到appsettings.json中的MyConfigValue,但HandleAuthenticateAsync方法里的Options.MyConfigValue始终为null。
  • 已用[Authorize(AuthenticationSchemes = "ApiKey")]标记保护接口,appsettings.json根节点也配置了MyConfigValue,但认证时Options.MyConfigValue仍为null。
  • 若直接在处理器中读取配置可正常工作,但每次请求都读配置效率较低,希望找到问题根源并解决。

原因分析与解决方案

问题根源

你在调用AddScheme时传入了空的配置委托options => { },这会覆盖之前通过Configure<ApiKeyAuthenticationOptions>设置的全局配置。

在ASP.NET Core认证系统中,AddScheme方法的最后一个参数是用于配置当前Scheme专属选项的委托。当你传入空委托时,系统会创建一个全新的ApiKeyAuthenticationOptions实例(所有属性取默认值,比如MyConfigValue为null),并覆盖之前通过Configure注册的配置。

修复方法

修改AddApiKeyAuthentication扩展方法,移除空配置委托即可:

public static AuthenticationBuilder AddApiKeyAuthentication(this AuthenticationBuilder builder, IConfiguration configuration)
{
    var config = configuration["MyConfigValue"];
    builder.Services.Configure<ApiKeyAuthenticationOptions>(options =>
    {
        options.MyConfigValue = config;
    });

    // 移除空配置委托,直接使用全局配置
    builder.AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>(ApiKeyAuthenticationOptions.DefaultScheme);

    return builder;
}

额外优化建议

  1. ApiKeyAuthenticationOptions继承自AuthenticationSchemeOptions,无需自行定义Scheme和AuthenticationType属性,基类会自动处理Scheme名称。
  2. 建议将API Key配置放在专门的节点中,符合ASP.NET Core配置规范:
    • 在appsettings.json中添加:
      "ApiKeySettings": {
        "ValidApiKey": "your-actual-api-key"
      }
      
    • 创建对应配置类:
      public class ApiKeySettings
      {
          public string ValidApiKey { get; set; }
      }
      
    • 在ConfigureServices中绑定配置:
      services.Configure<ApiKeySettings>(Configuration.GetSection("ApiKeySettings"));
      
    这种方式更便于后续扩展多API Key等复杂场景。

内容的提问来源于stack exchange,提问作者user3901397

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 22:53:12