Thread.CurrentPrincipal已经过身份验证,但ClaimsPrincipal.Current不是

Jos*_*nke 7 c# identity claims-based-identity .net-4.5 asp.net-web-api

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

ClaimsPrincipal.Current.Identity.IsAuthenticated; //False
Thread.CurrentPrincipal.Identity.IsAuthenticated; //True
Run Code Online (Sandbox Code Playgroud)

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

备注

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

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

Dam*_*ver 10

简而言之,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);
    }
}
Run Code Online (Sandbox Code Playgroud)

这反过来,你可以看到希望,被返回ClaimsIdentity的是包装主体的身份(再次,如果它不是,其实已经是一个ClaimsIdentity).

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

if(identity is WindowsIdentity)
{
   try
   {
      this.m_authenticationType = identity.AuthenticationType;
   }
   catch(UnauthorizedAccessException)
   {
      this.m_authenticationType = null;
   }
}
Run Code Online (Sandbox Code Playgroud)

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

  • @JosVinke - 如果它已经是`ClaimsPrincipal`,那么以上所有都没有实际意义,因为它应该只返回相同的实例.是`ReferenceEquals(ClaimsPrincipal.Current,Thread.CurrentPrincipal)`是真的吗? (2认同)