Thread.CurrentPrincipal is authenticated but Claim

2019-06-17 02:27发布

问题:

I'm using Claims based Authorization in my WebApi project and have a method where I check if the current Identity is authenticated. When I use ClaimsPrincipal.Current the current Identity is not authenticated but when I use Thread.CurrentPrincipal it is.

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

This seems strange especially since the MSDN says ClaimsPrincipal.Current just returns Thread.CurrentPrincipal:

Remarks

By default, Thread.CurrentPrincipal is returned. You can change this behavior by setting the ClaimsPrincipalSelector property to specify a delegate to be called to determine the current principal.

Can someone please explain me why ClaimsPrincipal is not authenticated, while both, in theory, contain the same Identity?

回答1:

In short, the documentation is incorrect to say that it returns Thread.CurrentPrincipal by default.

What it actually returns is a ClaimsPrincipal wrapping Thread.CurrentPrincipal (if it's not, actually, already a ClaimsPrincipal), using this constructor:

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

This, in turn, as you can hopefully see, is returning a ClaimsIdentity that wraps the principal's identity (again, if it's not, actually, already a ClaimsIdentity).

In constructing the ClaimsIdentity, the only place I can see where it will end up not setting the authentication type (and thus creating an identity that's not authenticated) is here:

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

So, if the identity you access via Thread.CurrentPrincipal.Identity is actually a WindowsIdentity instance, and in the context in which you're running you've got restricted permissions, the constructed ClaimsIdentity instance will have IsAuthenticated as false.