Почему мой ClaimsIdentity IsAuthenticated всегда false (для фильтра авторизации веб-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;
}

а затем позже, когда я применяю [Authorize] атрибут контроллера, он не может авторизоваться.

код отладки подтверждает то же самое поведение:

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

почему он думает, что пользователь не аутентифицируется, даже если я построил действительный ClaimsIdentity и назначил его потоку?

2 53

2 ответа:

проблема из-за критического изменения в .Net 4.5. Как объяснил в этой статье, простое построение идентификатора утверждений больше не делает его IsAuthenticated return true. Вместо этого вам нужно передать некоторую строку (не имеет значения, что) в конструктор.

вот эта строка в приведенном выше коде:

var claimsIdentity = new ClaimsIdentity( claims );

становится этот:

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

и проблема решена. обновление: см. другой ответ от Лео. Точное Значение AuthenticationType может быть или не быть важным в зависимости от того, что еще у вас есть в конвейере auth.

обновление 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