【问题标题】:How to merge multiple authentication schema in one (Custom Authentication)如何将多个身份验证模式合并为一个(自定义身份验证)
【发布时间】:2020-07-01 16:31:25
【问题描述】:

我在我的 .NET Core API 中使用add multiple Jwt bearer 进行了多重身份验证,假设我有Schema1Schema2Schema3

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

但由于 Ocelot 只是让我添加一个架构名称,我必须将这 3 个架构合并为 1 个架构。

所以基本问题是:我如何定义一个通过Schema1Schema2Schema3 进行身份验证的身份验证模式(SchemaX)?有什么想法吗?

【问题讨论】:

    标签: authentication .net-core asp.net-core-webapi ocelot asp.net-core-authenticationhandler


    【解决方案1】:

    您可以尝试创建自定义 AuthorizeFilter 以允许多个身份验证架构,例如 here 或编写自定义中间件,从 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();
    });
    

    当然你也可以将认证逻辑从三个方案移到一个方案中。

    【讨论】:

      【解决方案2】:

      这很简单,如果有人在寻找,我在这里回答:

      基本上只需要定义一个custom AuthenticationHandler

      public class DynamicAuthenticationOptions : AuthenticationSchemeOptions
      {
      }
      
      public class DynamicAuthenticationHandler : AuthenticationHandler<DynamicAuthenticationOptions>
      {
      
          public DynamicAuthenticationHandler(
              IOptionsMonitor<DynamicAuthenticationOptions> options,
              ILoggerFactory logger,
              UrlEncoder encoder,
              ISystemClock clock
          )
              : base(options, logger, encoder, clock)
          {
          }
      
          protected override Task<AuthenticateResult> HandleAuthenticateAsync()
          {
              if (!Request.Headers.ContainsKey("Authorization"))
                  return Task.FromResult(AuthenticateResult.Fail("Unauthorized"));
      
              string authorizationHeader = Request.Headers["Authorization"];
              if (string.IsNullOrEmpty(authorizationHeader))
                  return Task.FromResult(AuthenticateResult.Fail("Unauthorized"));
      
              if (!authorizationHeader.StartsWith("bearer", StringComparison.OrdinalIgnoreCase))
                  return Task.FromResult(AuthenticateResult.Fail("Unauthorized"));
      
              var token = authorizationHeader.Substring("bearer".Length).Trim();
      
              IEnumerable<Claim> claims;
      
              foreach (var validMergedSchema in validMergedSchemas)
              {
                  if (IsTokenValid(token, validMergedSchema, out claims))
                  {
                      var identity = new ClaimsIdentity(claims, Scheme.Name);
                      var principal = new System.Security.Principal.GenericPrincipal(identity, null);
                      var ticket = new AuthenticationTicket(principal, Scheme.Name);
                      return Task.FromResult(AuthenticateResult.Success(ticket));
                  }
              }
      
              return Task.FromResult(AuthenticateResult.Fail("Unauthorized"));
      
          }
      
          private bool IsTokenValid(string tokenStr, string schema, out IEnumerable<Claim> claims)
          {
              claims = null;
      
              switch (schema.ToLower())
              {
                  case "schema1":
                      return IsTokenValidBySchema1(tokenStr, out claims);
      
                  case "schema2":
                      return IsTokenValidBySchema2(tokenStr, out claims);
      
                  case "schema3":
                      return IsTokenValidBySchema3(tokenStr, out claims);
      
                  default:
                      return false;
              }
      
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2020-04-01
        • 2022-12-10
        • 2018-09-26
        • 2020-04-02
        • 2016-08-04
        • 2012-10-23
        • 1970-01-01
        • 2010-12-17
        • 1970-01-01
        相关资源
        最近更新 更多