C# 为什么我的ClaimsIdentity IsAuthenticated总是false(对于web api授权筛选器)?
在一个WebAPI项目中,我将覆盖正常的身份验证过程来检查令牌。代码如下所示: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=
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
。在过去的两年里,我两次遇到同样的非直觉问题,这个答案再次帮助了我。不幸的是,我无法两次否决这个答案。