C# 为什么我的ClaimsIdentity IsAuthenticated总是false(对于web api授权筛选器)?

C# 为什么我的ClaimsIdentity IsAuthenticated总是false(对于web api授权筛选器)?,c#,asp.net,asp.net-web-api,claims-based-identity,asp.net-4.5,C#,Asp.net,Asp.net Web Api,Claims Based Identity,Asp.net 4.5,在一个WebAPI项目中,我将覆盖正常的身份验证过程来检查令牌。代码如下所示: if(true)//在此处验证令牌或其他内容 { var索赔=新列表(); claims.Add(新索赔(ClaimTypes.Name,“MyUser”); 添加(新的索赔(ClaimTypes.NameIdentifier,“MyUserID”); claims.Add(新索赔(ClaimTypes.Role,“MyRole”); var Claimsidenty=新的索赔(索赔); var principal=

在一个WebAPI项目中,我将覆盖正常的身份验证过程来检查令牌。代码如下所示:

if(true)//在此处验证令牌或其他内容
{
var索赔=新列表();
claims.Add(新索赔(ClaimTypes.Name,“MyUser”);
添加(新的索赔(ClaimTypes.NameIdentifier,“MyUserID”);
claims.Add(新索赔(ClaimTypes.Role,“MyRole”);
var Claimsidenty=新的索赔(索赔);
var principal=newclaimsprincipal(new[]{claimsIdentity});
Thread.CurrentPrincipal=主体;
HttpContext.Current.User=主体;
}
然后,当我将
[Authorize]
属性应用于控制器时,它无法进行授权

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

//始终为FALSE!
if(HttpContext.Current.User.Identity.IsAuthenticated){
//做点什么
}

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

问题在于.Net 4.5中的一个重大更改。正如所解释的,简单地构造一个声明标识不再使其成为经过身份验证的返回。相反,您需要将一些字符串(不管是什么)传递到构造函数中

因此,上述代码中的这一行:

var claimsIdentity=新的索赔(索赔);
变成这样:

//精确的字符串并不重要
var claimsIdentity=新的索赔实体(索赔,“CustomApiKeyAuth”);
问题解决了更新:请参阅Leo的其他答案。确切的AuthenticationType值可能重要,也可能不重要,这取决于auth管道中的其他内容

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

var claimsIdentity=新的claimsIdentity(声明、身份验证类型、密码);
//在应用程序的其他地方。。。
if(User.Identity.AuthenticationType==AuthenticationTypes.Password){
// ...
}

虽然提供的答案有一定的正确性,但并不完全正确。你不能假设仅仅添加任何字符串就能神奇地工作。如其中一条注释所述,此字符串必须与枚举之一匹配,而枚举必须与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
                });            
        }
然而,在上述情况下,这并不重要。但是,如果您使用更多的身份验证/授权级别,则声明将与与相同的
AuthenticationType
匹配的声明相关联…另一个示例是使用cookie身份验证时

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

其中,
AuthenticationType
描述了cookie的名称,由于您的应用程序可能从其他提供商处获得了其他cookie,因此在实例化声明时设置
AuthenticationType
非常重要,以便将其与正确的cookie关联

,尽管您可以添加任何字符串,根据MSDN,这通常应该是AuthenticationTypes类中定义的值之一。示例:var claimsIdentity=新的claimsIdentity(claims,AuthenticationTypes.Password);字符串的值在User.Identity.authenticationType哇中变得可见,这真是晦涩难懂!谢谢分享!我被卡住了一个多小时。在.NET Core中,您可以使用常量作为
AuthenticationType
,例如。或者。注意,在创建
ClaimsIdentity
时,您需要将架构名称作为
AuthenticationType
(如
新的ClaimsIdentity(声明、身份验证方案)
)。否则,标识上的
IsAuthenticated
标志将为
false
。在过去的两年里,我两次遇到同样的非直觉问题,这个答案再次帮助了我。不幸的是,我无法两次否决这个答案。