强制执行基于 API 密钥的身份验证时无法使自定义选项起作用

问题描述 投票:0回答:1

我有一个 ASP.NET Core 3.1 Web API 项目,没有强制执行安全性。现在我需要使用基于 API 密钥的身份验证方案来保护它。

基本思想是让此 Web API 的客户端在标头中传入 API 密钥,然后所有客户端 API 密钥将保存在

appsettings.json
文件中。

这些是实施细节:

  1. 设置自定义
    ApiKeyAuthenticationOptions
    ,其中
    MyConfigValue
    将用于按住按键
    public class ApiKeyAuthenticationOptions : AuthenticationSchemeOptions
    {
        public const string DefaultScheme = "ApiKey";
        public string Scheme => DefaultScheme;
        public string AuthenticationType = DefaultScheme;
        public string MyConfigValue { get; set; }
    }
  1. 启动时,认证逻辑被添加到服务集合中
    public void ConfigureServices(IServiceCollection services)
    {
            services.AddSingleton(Configuration);
         services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
             .AddApiKeyAuthentication(Configuration);
         services.AddControllers();
    }
  1. AuthenticationBuilder
    的扩展方法定义为
    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. 身份验证处理程序定义为
    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
中的
constructor
有一个属性
CurrentValue
,该属性具有自定义属性
MyConfigValue
,具有来自
appsettings
的正确值,但是,在函数
HandleAuthenticateAsync
中,
Options 
没有属性
CurrentValue
,但它具有自定义属性
MyConfigValue
,该属性为 null。因此,构造函数中的
options
与函数中的
Options
不一样。我对
ApiKeyAuthenticationHandler
类的实现可能是错误的。现在的一种解决方法是检索
MyConfigValue
内的
constructor
并将其保存以供在函数中使用。

  1. 使用以下方式保护 API 调用:

    [Authorize(AuthenticationSchemes = "ApiKey")]
    
  2. 我将

    MyConfigValue
    设置在
    appsettings.json
    的根级别。
    但是,每当安全 API 调用触发调用函数
    HandleAuthenticateAsync
    时,
    options.MyConfigValue
    始终为 null。
    一旦我使用默认的
    ApiKeyAuthenticationOptions
    而不包含
    MyConfigValue
    ,然后在
    ApiKeyAuthenticationHandler
    中获取它,那么它就可以工作。但这需要为每个 API 调用获取
    MyConfigValue
    ,效率不高。
    Visual Studio 2022 中有一个简单的解决方案,如果需要,我可以提供。我也会想办法上传到GitHub。

有人可以告诉我出了什么问题吗?

提前非常感谢。

c# asp.net-core authentication configuration asp.net-core-webapi
1个回答
0
投票

builder.AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>(ApiKeyAuthenticationOptions.DefaultScheme, options => {  });
重置导致您出现问题的ApiKeyAuthenticationOptions。

您应该直接使用

builder.AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>(ApiKeyAuthenticationOptions.DefaultScheme, options => { options.MyConfigValue = configuration["MyConfigValue"];  });

详情如下:

public static class AuthenticationBuilderExtensions
{
    public static AuthenticationBuilder AddApiKeyAuthentication(this AuthenticationBuilder builder, IConfiguration configuration)
    {
        var config = configuration["MyConfigValue"];

        builder.AddScheme<ApiKeyAuthenticationOptions, ApiKeyAuthenticationHandler>(ApiKeyAuthenticationOptions.DefaultScheme, options => { options.MyConfigValue = configuration["MyConfigValue"];  });

        return builder;
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.