【问题标题】:Where to filter Identity 2.0 claim ticket in a WebAPI app?在 WebAPI 应用程序中在哪里过滤 Identity 2.0 声明票证?
【发布时间】:2015-06-03 15:38:39
【问题描述】:

使用 OWIN 的 ASP.NET 应用程序允许多个身份源(Facebook、Google 等)。这些来源提供的大多数特定于提供商的信息与我的应用程序无关,甚至可能很大,而且我不希望它在我的所有会话中出现。我的应用主要是 WebAPI,但我怀疑这个问题同样适用于 MVC 和 WebForms。

现在,我只需要一个整数帐户 ID。 外部身份验证后,我应该在何处/何时重建身份?

例如,这是我可以过滤声明的一种方式:

public ReplaceExistingClaims(ClaimsIdentity identity) {
{
    Claim customClaim = GetCustomClaimFromDbForIdentity(identity);
    foreach (Claim claim in ClaimsIdentity.Claims) ClaimsIdentity.RemoveClaim(claim);
    ClaimsIdentity.AddClaim(customClaim);
}

以下是我可以注入这些声明更改的两个不同地方:

var facebookAuthenticationOptions = new FacebookAuthenticationOptions
{
    Provider = new FacebookAuthenticationProvider
    {
        OnAuthenticated = context =>
        {
            ReplaceExistingClaims(context.Identity);
            return Task.FromResult(0);
        }
    }
};

上面,我知道我可以从Startup 钩住一个单独的提供者,如果它提供了一个Authenticated 事件。我对此有两个概念性问题。一:它要求我为我插入的每个提供者分别编写和连接我的代码。二:不需要提供者提供此事件。这两个都让我觉得我的代码必须有一个不同的预期插入点。

public ActionResult ExternalLoginCallback(string returnUrl)
{
    ReplaceExistingClaims((ClaimsIdentity)User.Identity);
    new RedirectResult(returnUrl);
}

以上,我知道我可以在ExternalLoginCallback 中输入代码。但这发生得太晚了,原因有两个。一:用户已经收到一张我认为无效的票,但默认的[Authorized] 认为有效,因为它是由我签名的,现在他们正在用它向我的网站发出请求。这里甚至可能存在竞争条件。二:不能保证浏览器会访问这个重定向,如果不需要的话,我更喜欢从设计的角度来看,例如简化我的 WebAPI 客户端代码。

据我所知,最佳解决方案将满足以下要求:

  1. 相同的代码适用于所有提供商
  2. 客户端从我的服务器接收我的自定义票证(例如,没有图像声明)
  3. 客户端永远不会从我的服务器收到另一种票证格式
  4. 身份验证过程需要尽可能少的 HTTP 往返
  5. 令牌刷新和其他核心身份功能仍然可用
  6. 一旦用户是[Authorize]d,就不需要进一步的帐户转换
  7. 在票证生成期间可以访问数据库/存储库

我正在研究的一些页面,作为我自己的笔记:

【问题讨论】:

  • 能否请您澄清一下流程是什么?
  • 当然。应用程序访问尝试 -> Facebook/Google 身份验证 -> 自定义票证分配 -> 授权。这可能会跟随:附加访问尝试 -> 自定义票证演示 -> 授权。自定义票证将包含完成此操作所需的最低要求,而身份验证协商可能会产生其他额外数据,例如个人资料照片。
  • 基本上您需要向服务器发送请求以使用任何提供商登录?这个请求应该是异步的?在您登录后,客户端应该会收到通知并加载相关信息?
  • @deeptowncitizen :您在询问身份验证过程本身,我没有问题回答,但我认为这与我的问题无关。我对当前实施的 OAuth2 身份验证过程感到满意。我的问题是,在该身份验证过程之后,向用户的 Web 浏览器提供我的自定义身份票证的正确位置/方式是什么?默认情况下,Identity 2.0 生成的身份验证令牌 cookie 大约是我之前令牌大小的 100 倍,目前这不在我的控制范围内。

标签: asp.net-web-api asp.net-identity asp.net-web-api2 owin asp.net-identity-2


【解决方案1】:

ClaimsAuthenticationManager 类专门用于此。

https://msdn.microsoft.com/en-us/library/system.security.claims.claimsauthenticationmanager(v=vs.110).aspx

来自该参考的代码示例:

class SimpleClaimsAuthenticatonManager : ClaimsAuthenticationManager
{
    public override ClaimsPrincipal Authenticate(string resourceName, ClaimsPrincipal incomingPrincipal)
    {
        if (incomingPrincipal != null && incomingPrincipal.Identity.IsAuthenticated == true)
        {
            ((ClaimsIdentity)incomingPrincipal.Identity).AddClaim(new Claim(ClaimTypes.Role, "User"));
        }
        return incomingPrincipal; 
    }
}

【讨论】:

  • 附注我很高兴我遇到了这个问题,因为我正准备将它作为一个单独的 OWIN 垫片来实现。
  • 另外,在该文档中,“RP”代表“依赖方”。呃,一些技术作家需要被解雇。
【解决方案2】:

您必须实现DelegationHandler 并将所有身份验证例程放入其中。

在应用程序启动时注册(启用 DI 使用):

private static void RegisterHandlers(HttpConfiguration config)
{
    var authHandler = new MyFacebookAuthHandler();
    config.MessageHandlers.Add(authHandler);
}

这是一个实现的例子:

public class MyFacebookAuthHandler : DelegationHandler
{
    public override sealed Task<HttpResponseMessage> OnSendAsync(HttpRequestMessage request,
                                                                 CancellationToken cancellationToken)
    {
        try
        {
            // Process credentials
            // Probably you have to save some auth information to HttpContext.Current
            // Or throw NotAuthorizedException
        }
        catch(NotAuthorizedException ex)
        {
            return request.CreateErrorResponse(HttpStatusCode.Unauthorized, ex).ToCompletedTask();
        }
        catch (Exception ex)
        {
            return request.CreateErrorResponse(HttpStatusCode.InternalServerError, ex).ToCompletedTask();
        }

        return base.OnSendAsync(request, cancellationToken);
    }
}

【讨论】:

  • 感谢您的回复。我不确定你在这里做什么。我假设DelegationHandler 你实际上是指DelegatingHandlerOnSendAsyncSendAsync?如果是这样,我看不出这有什么帮助。我正在寻找修改提供给客户的声明。这应该发生一次,即身份验证完成的那一刻。他们仍然需要首先进行身份验证,并且该步骤通常需要将客户端重定向到外部提供商。因此,“凭据”不能真正在 MessageHandler 中处理。我误会你了吗?
  • 经过更多研究,我发现 DelegatingHandler 确实运行每个请求,类似于我已经用于获取外部身份验证的标准 OWIN 模块。如果我的问题不够清楚,我深表歉意。
猜你喜欢
  • 1970-01-01
  • 2015-11-29
  • 1970-01-01
  • 2015-03-02
  • 2015-03-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多