Как объединить несколько схем аутентификации в одну (Пользовательская аутентификация)

У меня есть множественная аутентификация в моем .NET Core API с использованием добавления нескольких JWT-носителей, предположим, что я есть Schema1, Schema2 и Schema3.

Я также использую Ocelot для управления запросами. В конфигурации Ocelot для каждого маршрута я мог объявить один и только один тип аутентификации (имя схемы). Однако в некоторых сценариях мне нужно иметь поддержку нескольких аутентификаций для каждого маршрута. (Мне нужно аутентифицировать запрос с помощью Schema1, Schema2 или Schema3).

Но так как Ocelot просто позволил мне добавить одно имя схемы, мне нужно объединить эти 3 схемы в 1 схему.

Итак, основной вопрос: как я могу определить одну схему аутентификации (SchemaX), которая аутентифицируется с помощью Schema1, Schema2 или Schema3? Есть идеи?




Ответы (2)


Вы можете попытаться создать собственный AuthorizeFilter, чтобы разрешить несколько схем аутентификации, например здесь, или написать собственное промежуточное программное обеспечение, которое проверяет маршрут URL-адреса из контекста http. и вручную вызывает 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();
});

Конечно, вы также можете перенести логику аутентификации из трех схем в одну.

person Nan Yu    schedule 23.03.2020

Это было просто, я отвечаю здесь, если кто-то ищет:

По сути, просто нужно определить пользовательский обработчик аутентификации:

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;
        }

    }
}
person Saeid    schedule 26.03.2020