【问题标题】:Thread.CurrentPrincipal is authenticated but ClaimsPrincipal.Current is notThread.CurrentPrincipal 已通过身份验证,但 ClaimsPrincipal.Current 未通过
【发布时间】:2013-03-11 15:06:54
【问题描述】:

我在我的 WebApi 项目中使用基于声明的授权,并且有一个方法可以检查当前身份是否经过身份验证。当我使用ClaimsPrincipal.Current 时,当前身份未经过身份验证,但当我使用Thread.CurrentPrincipal 时,它是。

ClaimsPrincipal.Current.Identity.IsAuthenticated; //False
Thread.CurrentPrincipal.Identity.IsAuthenticated; //True

这似乎很奇怪,尤其是因为 MSDN says ClaimsPrincipal.Current 只返回 Thread.CurrentPrincipal:

备注

默认情况下,返回 Thread.CurrentPrincipal。你可以改变这个 通过设置 ClaimsPrincipalSelector 属性来指定行为 调用委托以确定当前委托人。

谁能解释一下为什么ClaimsPrincipal 没有经过身份验证,而理论上两者都包含相同的身份?

【问题讨论】:

  • “默认情况下,” 对我来说暗示其他一些行为是可能的 - 你有没有裁定我们的?
  • No ClaimsPrincipalSelector 为空,所以使用默认值。

标签: c# asp.net-web-api .net-4.5 identity claims-based-identity


【解决方案1】:

简而言之,文档中说它默认返回Thread.CurrentPrincipal 是不正确的。

它实际返回的是ClaimsPrincipal 包装 Thread.CurrentPrincipal(如果不是,实际上,已经是ClaimsPrincipal),使用这个构造函数:

public ClaimsPrincipal(IPrincipal principal)
{
    this.m_version = "1.0";
    this.m_identities = new List<ClaimsIdentity>();
    if (principal == null)
    {
        throw new ArgumentNullException("principal");
    }
    ClaimsPrincipal principal2 = principal as ClaimsPrincipal;
    if (principal2 == null)
    {
        this.m_identities.Add(new ClaimsIdentity(principal.Identity));
    }
    else if (principal2.Identities != null)
    {
        this.m_identities.AddRange(principal2.Identities);
    }
}

反过来,正如您所希望看到的,它返回一个ClaimsIdentity包装主体的身份(同样,如果不是,实际上已经是一个ClaimsIdentity)。

在构造ClaimsIdentity 时,我唯一能看到它最终不会设置身份验证类型(并因此创建一个未经身份验证的身份)的地方是:

if(identity is WindowsIdentity)
{
   try
   {
      this.m_authenticationType = identity.AuthenticationType;
   }
   catch(UnauthorizedAccessException)
   {
      this.m_authenticationType = null;
   }
}

所以,如果您通过Thread.CurrentPrincipal.Identity 访问的身份实际上是一个WindowsIdentity 实例,并且在您运行的上下文中,您拥有受限权限,构造的@987654332 @instance 会将 IsAuthenticated 设为 false。

【讨论】:

  • Thread.CurrentPrincipal 在我的代码中包含一个 ClaimsPrincipal。从您发布的代码中,我看到一个列表已构建,但它并没有向我解释为什么 IsAuthenticated 设置为 false。是不是因为 ClaimsPrincipal 做了一些额外的验证失败了?我确实想知道为什么它是错误的,所以我可以修复失败的问题,或者将 claimprincipal 设置为经过身份验证,知道为什么它首先是错误的。
  • @JosVinke - 如果它已经是ClaimsPrincipal,那么以上所有内容都没有实际意义,因为它应该只返回相同的实例。 ReferenceEquals(ClaimsPrincipal.Current,Thread.CurrentPrincipal) 是真的吗?
  • 它确实返回 false,不同之处在于 ClaimsPrincipal.Current 是 System.Security.Claims.ClaimsPrincipal 而 Thread.CurrentPrincipal 是 Microsoft.IdentityModel.Claims.ClaimsPrincipal。但我仍然想知道为什么它被设置为 false。
  • @JosVinke - 在这种情况下,您正在混合较旧的 WIF 代码和较新的(嵌入核心)框架身份代码。所以它很可能会做我上面描述的一些包装。
  • 我也遇到了 Thread.CurrentPrincipal 和 ClaimsPrincipal.Current 之间的差异。在我的情况下,问题是我们使用 Windows 身份验证,但使用从数据库添加本地声明的过程。生成的 ClaimsPrincipal.Current 是一个 RolePrincipal,但因为 RolePrincipal 覆盖了 Identity,它正在从它自己的 Identity 而不是从基本 ClaimsPrincipal 的 Identity 中查找声明。解决方案是将 ClaimsPrincipalSelector 设置为始终根据现有的 Thread.CurrentPrincipal.Identity 返回一个新的 ClaimsPrincipal。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-07
相关资源
最近更新 更多