如何将 ApiKey 模式验证作为第二个验证模式添加到 .NET Core 中的 WebApi

How to add ApiKey schema validation as the second validation schema to a WebApi in .NET Core

我有一个 Web API,它已经 JwtBearer 进行了架构验证。现在我需要将 ApiKey 架构验证添加到 Web API 以供服务使用。

我遵循此 guide,创建 ApiKeyAttribute class 并使用 [ApiKey] 属性修饰控制器方法。

仍然,当我调用 Web API 方法时,出现 401 错误。

调用方式如下:

//add "Authentication: Bearer somekey" header to every http call
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("ApiKey", "somekey"); 

从未调用 ApiKeyAttribute class 的方法 OnActionExecutionAsync

我尝试将这样的身份验证模式添加到 Web API 启动,但完全没有成功:

builder.Services    
 .AddControllers().Services
 .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) 
 ...
 .AddAuthentication("ApiKey").Services //the second schema, ApiKey
 .Add...

相反,它 returns

No authenticationScheme was specified, and there was no DefaultChallengeScheme found. The default schemes can be set using either AddAuthentication(string defaultScheme) or AddAuthentication(Action configureOptions).

有什么线索吗?

更新 25-04-2002

为了完整起见,我在这里添加了所有相关部分的代码。在我尝试在开始时添加 ApiKey 方案之前,它适用于 Bearer 方案。

属性class:

[AttributeUsage(validOn: AttributeTargets.Class | AttributeTargets.Method)]
public class ApiKeyAttribute : Attribute, IAsyncActionFilter
{
    private const string APIKEYNAME = "ApiKey";
    public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
    {
        Console.WriteLine("ApiKeyAttribute  HIT !!!"); //not passing here
        if (!context.HttpContext.Request.Headers.TryGetValue(APIKEYNAME, out var extractedApiKey))
        {
            context.Result = new ContentResult()
            {
                StatusCode = 401,
                Content = "Api Key was not provided"
            };
            return;
        }

        var appSettings = context.HttpContext.RequestServices.GetRequiredService<IConfiguration>();

        var apiKey = appSettings.GetValue<string>(APIKEYNAME);

        if (!apiKey.Equals("TESTE"))
        {
            context.Result = new ContentResult()
            {
                StatusCode = 401,
                Content = "Api Key is not valid"
            };
            return;
        }

        await next();
    }
}

带有修饰方法的控制器 ApiKey:

[ApiController]
[Route("[controller]")]

public class SomeController : ControllerBase
{
...

    [HttpGet()]
    [Produces("application/json")]
    //[Authorize(Roles = Roles.Read)] removed temporarily so i can put ApiKey scheme before i enable again the Bearer scheme that allows Role authorization. It is desirable to enable both schemes on same methods. 
    [ApiKey]
    public List<Rule> foo() {
      ...
    }
}

节目:

 var builder = WebApplication.CreateBuilder(args);
 ... //configs
 builder.Services    
 .AddControllers().Services
 .AddAuthentication(JwtBearerDefaults.AuthenticationScheme) 
 ...
 .AddAuthentication("ApiKey").Services //the second schema, ApiKey
 .Add...

var app = builder.Build();
...
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

app.MapControllerRoute(
    name: "default",
    pattern: "{controller}/{action=Index}/{id?}");

app.MapFallbackToFile("index.html"); ;
app.Run();

更新 26-04-2026

使用属性 class 似乎不是实现 ApiKey 模式验证的方法,或者至少我未能将其付诸实践。

我将 ApiKey 模式验证实现更改为发布的 here。作为唯一的模式验证效果很好。 仍然需要了解如何将其添加为第二个验证模式。

为控制器显式设置身份验证方案。

[ApiController]
[Route("[controller]")]
[Authorize(AuthenticationSchemes = "ApiKey")]
public class SomeController : ControllerBase
{
    // ACTIONS
}

要设置第二个身份验证方案,您可以使用以下方法:

[ApiController]
[Route("[controller]")]
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme + "," + apiKey.ApiKeyAuthenticationDefaults.AuthenticationScheme)]
public class SomeController : ControllerBase
{
    // ACTIONS
}