在一个Web API项目中,我替代了常规的身份验证过程来检查 token 。代码看起来像这样:

if ( true ) // validate the token or whatever here
{
    var claims = new List<Claim>();
    claims.Add( new Claim( ClaimTypes.Name, "MyUser" ) );
    claims.Add( new Claim( ClaimTypes.NameIdentifier, "MyUserID" ) );
    claims.Add( new Claim( ClaimTypes.Role, "MyRole" ) );

    var claimsIdentity = new ClaimsIdentity( claims );

    var principal = new ClaimsPrincipal( new[] { claimsIdentity } );
    Thread.CurrentPrincipal = principal;
    HttpContext.Current.User = principal;
}

然后,当我将[Authorize]属性应用于 Controller 时,它无法授权。

调试代码确认相同的行为:

// ALWAYS FALSE!
if ( HttpContext.Current.User.Identity.IsAuthenticated ) {
    // do something
}

为什么即使我已经构建了有效的ClaimsIdentity并将其分配给线程,用户仍未通过身份验证?

最佳答案

问题是由于.Net 4.5中的重大更改。如this article所述,仅构造声明身份不再使IsAuthenticated返回true。相反,您需要将一些字符串(无关紧要)传递给构造函数。

因此以上代码中的这一行:

var claimsIdentity = new ClaimsIdentity( claims );

变成这个:

// exact string doesn't matter
var claimsIdentity = new ClaimsIdentity( claims, "CustomApiKeyAuth" );

问题就解决了。 更新:查看来自Leo的其他答案。确切的AuthenticationType值可能重要,也可能不重要,具体取决于您在身份验证管道中还有哪些内容。

更新2:如Robin van der Knaap在评论中所建议,System.Security.Claims.AuthenticationTypes值之一可能是合适的。

var claimsIdentity = new ClaimsIdentity( claims, AuthenticationTypes.Password );

// and elsewhere in your application...
if (User.Identity.AuthenticationType == AuthenticationTypes.Password) {
    // ...
}

09-04 00:41