【问题标题】:How can I have multiple authentication methods with only one having to succeed?我怎样才能拥有多种身份验证方法而只有一种必须成功?
【发布时间】:2021-01-14 23:16:18
【问题描述】:

很遗憾,在这件事上我找不到任何可以帮助我的东西。

API 通常使用 OIDC 来处理身份验证,因此我们默认使用普通的 .AddAuthentication.AddJwtBearer。这很好用,但是我们还需要能够有另一种身份验证方式来提供用户身份,因为令牌并不总是可用的。假设这将是一些 ApiKey,其中包含给定 ApiKey 的用户字典。

不过,我希望 JWT 令牌优先于这一层,因为它只是一种更强的身份验证。所以它会是这样的:

  1. 我们收到请求
  2. 如果我们看到 Authorization 标头,则表示请求提供了令牌 - 我们想要验证该令牌,如果它无效 - 我们想要 401,因为有些事情不正确。
  3. 如果 HttpRequest 中没有 Authorization 标头,但我们有 ApiKey 标头 - 我们希望完全省略验证令牌并尝试检查该 ApiKey。如果它有效,我们想从那里设置 HttpContext.User 并告诉整个身份验证正常,我们的控制器可以正常使用 HttpContext.User。

目前我们有多个支持令牌或 ApiKey(不同属性)场景的控制器端点,但是当控制器和端点的数量增加时,复制所有内容可能会非常痛苦。

我尝试附加到一些 JwtBearerEvents 并检查那里的标头,以便如果我发现我们没有可用的令牌,我可以手动完成身份验证,例如:

OnMessageReceived = async context =>
{
    if (!context.Request.Headers.ContainsKey("Authorization") 
        && context.Request.Headers.ContainsKey("ApiKey"))
    {
         // some logic to check that ApiKey
         context.Principal = new ClaimsPrincipal(new ClaimsIdentity(
             new Claim[]
             {
                 new Claim(ClaimTypes.NameIdentifier, "ApiKeyUser")
             }));
         context.Success();
    }
    await Task.CompletedTask;
}

不幸的是,中间件仍然坚持检查令牌并返回 401,因此这很可能不是解决该问题的有效方法。

【问题讨论】:

    标签: c# asp.net-core


    【解决方案1】:

    我找到了一种方法,所以我将把它留在这里。您可以使用AddPolicyScheme 添加选择器,通过名称调用它们将使用不同的处理程序。

    例如:

    services.AddAuthentication(options =>
            {
                options.DefaultAuthenticateScheme = smartAuthenticationScheme; // just some string
                options.DefaultChallengeScheme = smartAuthenticationScheme;
                options.DefaultScheme = smartAuthenticationScheme;
            })
            .AddPolicyScheme(smartAuthenticationScheme, "Token / Custom", options =>
            {
                options.ForwardDefaultSelector = context =>
                {
                    var header = (string)context.Request.Headers["Authorization"];
    
                    if (header == null || string.IsNullOrEmpty(header))
                        return undefinedAuthenticationScheme;
    
                    if (header.StartsWith("Bearer"))
                        return bearerAuthenticationScheme; // it's just JwtBearerDefaults.AuthenticationScheme
                    if (header.StartsWith("Custom"))
                        return customAuthenticationScheme;
    
                    return undefinedAuthenticationScheme;
                };
            })
            .AddJwt(bearerAuthenticationScheme, configuration)
            .AddCustom(customAuthenticationScheme)
            .AddUndefined(undefinedAuthenticationScheme);
    

    这样,我们的中间件将查看 Authorization 标头的内容并调用以给定名称注册的 AuthenticationHandler。 UndefinedHandler 仅在 Authorization 标头的内容既不匹配 Jwt 也不匹配 Custom AuthorizationHandler 时提供 401 响应。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-13
      • 2020-01-03
      • 2016-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多