我有一个ASP.NET Core WebAPI(2.2),它使用两种类型的身份验证:
这是我在 Startup.cs 中进行配置的方式:
services.AddAuthentication(sharedOptions =>
{
sharedOptions.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddApiKeyAuthentication(options => Configuration.Bind("ApiKeyAuth", options));
services.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(jwtOptions =>
{
jwtOptions.Authority = $"https://login.microsoftonline.com/tfp/{Configuration["AzureAdB2C:Tenant"]}/{Configuration["AzureAdB2C:Policy"]}/v2.0/";
jwtOptions.Audience = Configuration["AzureAdB2C:ClientId"];
jwtOptions.Events = new JwtBearerEvents
{
OnAuthenticationFailed = AuthenticationFailed
};
});
我的控制器装饰有一个Authorize
属性,其中包括两个方案。因此,我可以使用承载令牌或通过在标头中指定API密钥来调用我的网络方法-很好。
现在,我添加了一个自定义的中间件,在其中执行一些特定于租户的检查。我在Configure
方法内(在UseAuthentication
之后)注册了中间件:
// ....
app.UseAuthentication();
app.UseMiddleware<CustomMiddleware>()
现在,如果我使用 bearer 身份验证来调用REST方法,那么我的CustomMiddleware
会被一个经过身份验证的用户调用-我可以来访问声明。
如果我使用自定义的 APIKey 身份验证调用相同 REST方法,我的CustomMiddleware
在我的{{1 }} 方法。用户未经身份验证-我无法访问声明(我在AuthenticationHandler.HandleAuthenticateAsync()
方法中填充了声明)。
为什么在身份验证之前调用中间件?如何更改行为,以使中间件在HandleAuthenticateAsync
之后被称为之后?
答案 0 :(得分:1)
您需要设置一个转发默认选择器,以在需要时将API密钥身份验证方案设为默认设置。
这是一个例子:
services.AddAuthentication(options =>
{
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(jwtOptions =>
{
jwtOptions.Authority = $"https://login.microsoftonline.com/tfp/{Configuration["AzureAdB2C:Tenant"]}/{Configuration["AzureAdB2C:Policy"]}/v2.0/";
jwtOptions.Audience = Configuration["AzureAdB2C:ClientId"];
jwtOptions.Events = new JwtBearerEvents
{
OnAuthenticationFailed = AuthenticationFailed
};
jwtOptions.ForwardDefaultSelector = ctx =>
{
if (ctx.Request.Headers.TryGetValue("Api-Key", out var headerValues))
{
return "ApiKeyAuth";
}
return null;
};
})
.AddApiKeyAuthentication(options => Configuration.Bind("ApiKeyAuth", options));
我猜测要构造选择器, 但基本上,如果需要使用其他方案,它需要返回另一个方案的名称, 否则为null。
在示例中,它检查请求中是否有“ Api-Key”标头, 如果是,则返回“ API密钥方案”的名称“ ApiKeyAuth”。 如果它们不同,则将其交换为您的值。
如果在两种方案中都使用了Authorization:Bearer xyz标头, 您需要检查选择器中的标题内容才能做出决定。