Authentication 如何将多个身份验证架构合并到一个架构中(自定义身份验证)

Authentication 如何将多个身份验证架构合并到一个架构中(自定义身份验证),authentication,.net-core,asp.net-core-webapi,ocelot,asp.net-core-authenticationhandler,Authentication,.net Core,Asp.net Core Webapi,Ocelot,Asp.net Core Authenticationhandler,我在.NET核心API中使用了多重身份验证,假设我有Schema1、Schema2和Schema3 我还使用它来管理请求。在Ocelot配置中,我可以为每个路由声明一个且只有一个身份验证类型(模式名)。但是,在某些情况下,我需要为每个路由提供多个身份验证支持。(我需要使用Schema1、Schema2或Schema3对请求进行身份验证) 但由于Ocelot只允许我添加一个模式名,因此我必须将这3个模式合并为1个模式 因此,基本问题是:如何定义一个通过Schema1或Schema2或Schema3

我在.NET核心API中使用了多重身份验证,假设我有
Schema1
Schema2
Schema3

我还使用它来管理请求。在Ocelot配置中,我可以为每个路由声明一个且只有一个身份验证类型(模式名)。但是,在某些情况下,我需要为每个路由提供多个身份验证支持。(我需要使用
Schema1
Schema2
Schema3
对请求进行身份验证)

但由于Ocelot只允许我添加一个模式名,因此我必须将这3个模式合并为1个模式


因此,基本问题是:如何定义一个通过
Schema1
Schema2
Schema3
进行身份验证的身份验证模式(
SchemaX
)?有什么想法吗?

您可以尝试创建自定义AuthorizeFilter以允许类似的多个身份验证模式,或者编写一个自定义中间件,从http上下文检查url路由,手动调用
AuthenticateAsync()
并创建一个
ClaimsPrincipal
包含您需要的所有身份,如:

app.UseAuthentication();
app.Use(async (context, next) =>
{
  var principal = new ClaimsPrincipal();

  var result1 = await context.AuthenticateAsync("MyScheme");
  if (result1?.Principal != null)
  {
      principal.AddIdentities(result1.Principal.Identities);
  }

  var result2 = await context.AuthenticateAsync("MyScheme2");
  if (result2?.Principal != null)
  {
      principal.AddIdentities(result2.Principal.Identities);
  }

  context.User = principal;

  await next();
});

当然,您也可以将身份验证逻辑从三个方案移动到一个方案中。

这很简单,如果有人想要:

基本上只需要定义一个:

公共类动态身份验证选项:身份验证方案选项
{
}
公共类DynamicAuthenticationHandler:AuthenticationHandler
{
公共DynamicAuthenticationHandler(
IOPTIONS监视器选项,
iLogger工厂记录器,
URL编码器,
系统时钟
)
:基本(选项、记录器、编码器、时钟)
{
}
受保护的覆盖任务handleAuthenticateAync()
{
if(!Request.Headers.ContainsKey(“授权”))
返回Task.FromResult(AuthenticateResult.Fail(“未经授权”);
字符串authorizationHeader=Request.Headers[“Authorization”];
if(string.IsNullOrEmpty(authorizationHeader))
返回Task.FromResult(AuthenticateResult.Fail(“未经授权”);
if(!authorizationHeader.StartsWith(“bearer”,StringComparison.OrdinalIgnoreCase))
返回Task.FromResult(AuthenticateResult.Fail(“未经授权”);
var token=authorizationHeader.Substring(“bearer.Length”).Trim();
i无数索赔;
foreach(validMergedSchema中的var validMergedSchema)
{
if(IsTokenValid(令牌、validMergedSchema、out声明))
{
var标识=新的索赔实体(索赔、方案、名称);
var principal=new System.Security.principal.GenericPrincipal(标识,null);
var票证=新的身份验证票证(主体,Scheme.Name);
返回Task.FromResult(AuthenticateResult.Success(票证));
}
}
返回Task.FromResult(AuthenticateResult.Fail(“未经授权”);
}
私有bool IsTokenValid(字符串tokenStr、字符串模式、out IEnumerable声明)
{
索赔=无效;
开关(schema.ToLower())
{
案例“方案1”:
返回IsTokenValidBySchema1(tokenStr,out索赔);
案例“schema2”:
返回IsTokenValidBySchema2(tokenStr,out索赔);
案例“schema3”:
返回IsTokenValidBySchema3(tokenStr,out索赔);
违约:
返回false;
}
}
}