7

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

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

这似乎很奇怪,特别是因为MSDN 说 ClaimsPrincipal.Current 只返回 Thread.CurrentPrincipal:

评论

默认情况下,返回 Thread.CurrentPrincipal。您可以通过设置 ClaimsPrincipalSelector 属性来更改此行为,以指定要调用的委托以确定当前主体。

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

4

1 回答 1

10

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

它实际返回的是一个ClaimsPrincipal 包装 Thread.CurrentPrincipal(如果不是,实际上,已经是 a 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包装主体身份的 a (同样,如果它不是,实际上已经是 a ClaimsIdentity)。

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

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

因此,如果您访问的身份Thread.CurrentPrincipal.Identity实际上是一个WindowsIdentity实例,并且在您运行的上下文中您拥有受限权限,则构造的ClaimsIdentity实例将具有IsAuthenticatedfalse。

于 2013-03-11T15:28:55.480 回答