Почему мой ClaimsIdentity IsAuthenticated всегда false (для фильтра авторизации веб-api)?
в проекте веб-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;
}
а затем позже, когда я применяю [Authorize]
атрибут контроллера, он не может авторизовать.
код отладки подтверждает то же самое поведение:
// ALWAYS FALSE!
if ( HttpContext.Current.User.Identity.IsAuthenticated ) {
// do something
}
почему он думает, что пользователь не аутентифицируется, даже если я построил действительное ClaimsIdentity и назначил его потоку?
2 ответов
проблема заключается в нарушении изменений в .Net 4.5. Как объяснил в этой статье, просто построение идентификатора утверждений больше не делает его IsAuthenticated возвращением true. Вместо этого вам нужно передать некоторую строку (не имеет значения, что) в конструктор.
вот эта строка в приведенном выше коде:
var claimsIdentity = new ClaimsIdentity( claims );
становится этот:
// exact string doesn't matter
var claimsIdentity = new ClaimsIdentity( claims, "CustomApiKeyAuth" );
и проблема решена. обновление: см. другой ответ от Лео. Точное Значение AuthenticationType может быть или не быть важным в зависимости от того, что еще у вас есть в конвейере аутентификации.
обновление 2: как предложил Робин ван дер Кнаап в комментариях, один из System.Security.Claims.AuthenticationTypes
значения могут быть уместны.
var claimsIdentity = new ClaimsIdentity( claims, AuthenticationTypes.Password );
// and elsewhere in your application...
if (User.Identity.AuthenticationType == AuthenticationTypes.Password) {
// ...
}
хотя предоставленный ответ имеет некоторую обоснованность, он не совсем корректен. Вы не можете предположить, что просто добавление любой строки будет волшебным образом работать. Как сказано в одном из комментариев, эта строка должна соответствовать одному из 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
});
}
однако в приведенном выше сценарии это не имело бы большого значения. Но, если вы используете больше уровни аутентификации / авторизации утверждения будут связаны с тем, который соответствует тому же AuthenticationType
...Другим примером является использование проверки подлинности cookie...
public void Configuration(IAppBuilder app)
{
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = "ApplicationCookie",
LoginPath = new PathString("/auth/login")
});
}
здесь AuthenticationType
описывает имя файла cookie, так как ваше приложение может получить другие файлы cookie от других поставщиков важно, чтобы вы установили AuthenticationType
при создании экземпляра утверждений, чтобы связать их с правильным cookie