C# 在中间件之前调用自定义AuthenticationHandler
我有一个ASP.NET核心WebAPI(2.2),它使用两种身份验证类型:C# 在中间件之前调用自定义AuthenticationHandler,c#,asp.net-core,.net-core,C#,Asp.net Core,.net Core,我有一个ASP.NET核心WebAPI(2.2),它使用两种身份验证类型: JWT承载者 APIKey(自定义) 这是我在Startup.cs中配置它的方式: services.AddAuthentication(sharedOptions=> { sharedOptions.DefaultAuthenticateScheme=JwtBearerDefaults.AuthenticationScheme; sharedOptions.DefaultChallengeScheme=JwtBea
- JWT承载者
- APIKey(自定义)
services.AddAuthentication(sharedOptions=>
{
sharedOptions.DefaultAuthenticateScheme=JwtBearerDefaults.AuthenticationScheme;
sharedOptions.DefaultChallengeScheme=JwtBearerDefaults.AuthenticationScheme;
})
.AddApiKeyAuthentication(options=>Configuration.Bind(“ApiKeyAuth”,options));
services.AddAuthentication(选项=>
{
options.DefaultScheme=JwtBearerDefaults.AuthenticationScheme;
})
.AddJwtBearer(jwtOptions=>
{
jwtOptions.Authority=$”https://login.microsoftonline.com/tfp/{Configuration[“AzureAdB2C:Tenant”]}/{Configuration[“AzureAdB2C:Policy”]}/v2.0/”;
jwtOptions.accession=Configuration[“AzureAdB2C:ClientId”];
事件=新的JWTBeareEvents
{
OnAuthenticationFailed=身份验证失败
};
});
我的控制器由一个Authorize
属性修饰,该属性包含两个方案。因此,我可以使用承载令牌或通过在报头中指定API密钥来调用我的web方法,这很好
现在,我添加了一个自定义中间件,在其中执行一些特定于租户的检查。我在Configure
方法中注册了中间件(在UseAuthentication
之后):
/。。。。
app.UseAuthentication();
app.UseMiddleware()
现在,如果我使用bearer身份验证调用REST方法,我的CustomMiddleware
将被一个经过身份验证的用户调用,我可以访问声明
如果使用自定义APIKey身份验证调用相同的REST方法,则在myAuthenticationHandler.handleAuthenticationAsync()方法之前调用myCustomMiddleware
。用户未通过身份验证-我无法访问声明(我在handleAuthenticateAncy
方法中填充了声明)
为什么在身份验证之前调用中间件?如何更改该行为,以便在handleAuthenticationAsync()
之后调用中间件?您需要设置一个前向默认选择器,以便在必要时将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));
我做了一些猜测来构造选择器,
但如果使用另一个方案,基本上需要返回另一个方案的名称,
否则无效
在本例中,它检查请求中是否有“Api密钥”头,
如果是,则返回“ApiKeyAuth”,这是API密钥方案的名称。
如果这些值不同,则将其替换为您的值
如果在两个方案中都使用了Authorization:Bearer xyz头,
您需要检查选择器中的标题内容才能做出决定。JWTBearner是否配置为默认身份验证方案?您的代码片段没有显示您是如何设置默认方案的。@KirkLarkin感谢您的帮助。我添加了我的精确配置。对于所讨论的REST方法,它是一个具有[Authorize]
属性的MVC操作。如果不是,那是什么?我意识到会有不止一种受影响的方法,但使用特定的示例更容易。我的所有控制器都使用从AuthorizeAttribute
继承的CustomeAuthorize属性,并将AuthenticationSchemes
设置为AuthenticationSchemes=“ApiKey,Bearer”代码>
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));