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

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

这看起来特别奇怪,因为MSDN saysclaimsprincipal.current只返回thread.currentprincipal:
评论
默认情况下,将返回thread.currentprincipal。你可以改变这个
通过设置ClaimsPrincipalSelector属性来指定
要调用以确定当前主体的委托。
有人能解释一下为什么ClaimsPrincipal没有被认证,而理论上两者都包含相同的身份吗?

最佳答案

简言之,文档不正确地说它默认返回Thread.CurrentPrincipal
它实际上返回的是一个包装(如果它实际上已经不是一个包装),使用这个构造函数:

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);
    }
}

反过来,正如您所希望看到的,这将返回一个封装主体身份的ClaimsPrincipal(如果不是,实际上已经是Thread.CurrentPrincipal)。
在构造ClaimsPrincipal时,我能看到的唯一一个不设置身份验证类型(从而创建未经身份验证的标识)的地方是:
if(identity is WindowsIdentity)
{
   try
   {
      this.m_authenticationType = identity.AuthenticationType;
   }
   catch(UnauthorizedAccessException)
   {
      this.m_authenticationType = null;
   }
}

因此,如果您通过ClaimsIdentity访问的标识实际上是一个ClaimsIdentity实例,并且在您运行的上下文中您具有受限权限,则构造的ClaimsIdentity实例将Thread.CurrentPrincipal.Identity设置为false。

08-25 23:52