Как объединить несколько схем аутентификации в одну (Custom Authentication) - PullRequest
0 голосов
/ 20 марта 2020

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

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

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

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

Ответы [ 2 ]

0 голосов
/ 26 марта 2020

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

В основном просто нужно определить пользовательский 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;
        }

    }
}
0 голосов
/ 23 марта 2020

Вы можете попытаться создать собственный 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();
});

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

...