为什么我的ClaimsIdentity IsAuthenticated始终为false(对于web api授权过滤器)?

exp*_*nit 65 c# asp.net claims-based-identity asp.net-4.5 asp.net-web-api

在Web API项目中,我重写了正常的身份验证过程来检查令牌.代码看起来像这样:

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;
}
Run Code Online (Sandbox Code Playgroud)

然后,当我将[Authorize]属性应用于控制器时,它无法授权.

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

// ALWAYS FALSE!
if ( HttpContext.Current.User.Identity.IsAuthenticated ) {
    // do something
}
Run Code Online (Sandbox Code Playgroud)

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

exp*_*nit 121

问题是由于.Net 4.5的突破性变化.正如本文所解释的那样,简单地构建声明标识不再使其IsAuthenticated返回true.相反,您需要将一些字符串(无关紧要)传递给构造函数.

所以在上面的代码中这一行:

var claimsIdentity = new ClaimsIdentity( claims );
Run Code Online (Sandbox Code Playgroud)

变成这样:

// exact string doesn't matter
var claimsIdentity = new ClaimsIdentity( claims, "CustomApiKeyAuth" );
Run Code Online (Sandbox Code Playgroud)

问题解决了.更新:请参阅Leo的其他答案.确切的AuthenticationType值可能重要,也可能不重要,具体取决于您在auth管道中的其他内容.

更新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) {
    // ...
}
Run Code Online (Sandbox Code Playgroud)

  • 虽然您可以添加任何字符串,但根据MSDN,这通常应该是AuthenticationTypes类中定义的值之一.http://msdn.microsoft.com/en-us/library/system.security.claims.claimsidentity.authenticationtype(v=vs.110).aspx (9认同)
  • 字符串的值在User.Identity.AuthenticationType中可见 (3认同)
  • 哇,这实在是太晦涩难懂了!感谢您在这里分享这个!我被困了一个多小时。 (2认同)

Leo*_*Leo 13

虽然提供的答案在其中有一定的有效性,但它并不完全正确.你不能假设只是添加任何字符串将神奇地工作.正如其中一条评论中所述,该字符串必须与AuthenticationTypes枚举中的一个匹配,而枚举又必须与OWIN认证/授权中间件中指定的枚举匹配....例如......

public void ConfigureOAuth(IAppBuilder app)
        {
            app.UseCors(CorsOptions.AllowAll);

            OAuthAuthorizationServerOptions serverOptions = new OAuthAuthorizationServerOptions()
            {
                AllowInsecureHttp = true,
                TokenEndpointPath = new Microsoft.Owin.PathString("/token"),
                AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
                AuthenticationType = AuthenticationTypes.Password,
                AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
                Provider = new AppAuthServerProvider()
            };


            app.UseOAuthAuthorizationServer(serverOptions);
            app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()
                {
                    AuthenticationMode = Microsoft.Owin.Security.AuthenticationMode.Active,
                    AuthenticationType = AuthenticationTypes.Password
                });            
        }
Run Code Online (Sandbox Code Playgroud)

但是,在上述情况下,这并不重要.但是,如果您使用更多身份验证/授权级别,声明将与匹配相同的声明关联AuthenticationType...另一个示例是当您使用Cookie身份验证时...

public void Configuration(IAppBuilder app)
        {
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = "ApplicationCookie",
                LoginPath = new PathString("/auth/login")
            });
        }
Run Code Online (Sandbox Code Playgroud)

其中AuthenticationType描述了cookie的名称,因为您的应用程序可能已从其他提供程序获取其他cookie,因此设置AuthenticationType实例化声明以便将其关联到正确的cookie非常重要.

  • 请注意,在创建“ClaimsIdentity”时,您需要将架构名称作为“AuthenticationType”传递(如“new ClaimsIdentity(claims, AuthenticationScheme)”)。否则身份上的“IsAuthenticated”标志将是“false”。在过去的两年里,我两次遇到同样的非直观问题,这个答案再次帮助了我。不幸的是,不能两次赞成这个答案。 (3认同)
  • 在.NET Core中,您可以使用常量作为“ AuthenticationType”,例如[CookieAuthenticationDefaults.AuthenticationScheme](https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.authentication.cookies.cookieauthenticationdefaults.authenticationscheme)或[JwtBearerDefaults.AuthenticationScheme](https://docs.microsoft.com/zh-cn/dotnet/api/microsoft.aspnetcore.authentication.jwtbearer.jwtbearerdefaults.authenticationscheme)。 (2认同)