0

Я с помощью проверки подлинности OAuth носителя, сконфигурированные как это в Startup.cs:OAuth: ASP.NET Web API User.Identity не загружает требования, установленные ключом аутентификации поставщика

 OAuthBearerAuthenticationOptions oAuthBearerOptions = 
      new OAuthBearerAuthenticationOptions 
      { 
       AccessTokenProvider = new AccessTokenProvider(), 
       AuthenticationMode = AuthenticationMode.Active 
      }; 
     app.UseOAuthBearerAuthentication(oAuthBearerOptions); 

... где AccessTokenProvider реализуется как:

public class AccessTokenProvider : AuthenticationTokenProvider 
{ 
    public override async Task ReceiveAsync(AuthenticationTokenReceiveContext context) 
    { 
     // Internal logic to get data needed for building identity... 

     // Create claims identity 
     ClaimsIdentity identity = new ClaimsIdentity(identityName); 
     identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, nameIdentifier)); 
     // Add other claims 

     // Set claims identity 
     context.SetTicket(new AuthenticationTicket(identity, new AuthenticationProperties())); 
    } 
} 

Если установить точку останова в конце ReceiveAsync, я могу подтвердить, что личность построена правильно (есть претензии) и что SetTicket достигается.

Но когда я пытаюсь получить доступ к идентичности из контроллера Web API:

public abstract class BaseStorageController : ApiController 
{ 
    protected IStorageService StorageService; 

    protected BaseStorageController(IStorageServiceFactory storageServiceFactory) 
    { 
     StorageService = storageServiceFactory.CreateStorageService(User.Identity as ClaimsIdentity); 
    } 

}

... список претензий на идентичность пуста!

Что может быть причиной этого?

Боковое примечание: я не знаю, связано ли это, но я использую Castle Windsor в качестве контейнера IOC для ввода зависимостей в мои контроллеры (в приведенном выше случае, IStorageServiceFactory). Выше, казалось, работа (претензии не были пустыми), прежде чем я добавил это. Однако я не использую CW для управления любыми объектами, связанными с аутентификацией. Вот мой установщик CW для контроллеров api:

public class ApiControllerInstaller : IWindsorInstaller 
{ 
    public void Install(IWindsorContainer container, IConfigurationStore store) 
    { 
     container.Register(Classes.FromThisAssembly().BasedOn<ApiController>().LifestylePerWebRequest()); 
    } 
} 

ответ

3

Я нашел ответ. Это не было связано с инжекцией/инверсией зависимости. Я не уверен, как я думал, что это работает до того, как это добавить.

Проблема похожа на то, что описано здесь (но в моем случае решение отличается): User (IPrincipal) not avaliable on ApiController's constructor using Web Api 2.1 and Owin

В основном IPrincipal не доступен из конструктора контроллера апи, поэтому нет никаких претензий (пользователь еще не аутентифицирован). User.Identity доступен только из действий контроллера, а не из конструктора. Я изменил мою реализацию базового контроллера к следующему, чтобы обойти эту проблему:

public abstract class BaseStorageController : ApiController 
{ 
    private readonly IStorageServiceFactory _storageServiceFactory; 
    private IStorageService _storageService; 

    protected BaseStorageController(IStorageServiceFactory storageServiceFactory) 
    { 
     _storageServiceFactory = storageServiceFactory; 
    } 

    protected IStorageService StorageService 
    { 
     get 
     { 
      if (_storageService == null) 
      { 
       _storageService = _storageServiceFactory.CreateStorageService(User.Identity as ClaimsIdentity); 
      } 
      return _storageService; 
     } 
    } 
} 

С StorageService только доступ из действий контроллера, User.Identity проверку подлинности и имеет претензии заселенных к тому времени, что StorageService геттер вызывается.

Надеюсь, это поможет кому-то!

+0

спасибо !!! У меня проблема с конструктором продолжалась весь день и пробовала несколько разных реализаций authprovider. Это решило это. –

0
protected IStorageService StorageService 
{ 
    get 
    { 
     if (_storageService == null) 
     { 
      _storageService = _storageServiceFactory.CreateStorageService(User.Identity as ClaimsIdentity); 
     } 
     return _storageService; 
    } 
} 

это не самый лучший подход для реализации DI

Это гораздо лучше использовать инъекции конструктора. Проверить Constructor Injection in C#/Unity? если вы не familliar с Unity, перейдите по этой ссылке, очень полезно: https://msdn.microsoft.com/en-us/library/dn223671(v=pandp.30).aspx

С уважением

+0

IPrincipal недоступен в конструкторе веб-контроллера api, что означает, что в этом случае впрыск конструктора не работает. – lucuma