2015-01-01 2 views
9

Я реализую идентификатор ASP.Net 2 в системе WebApi. Для управления электронного письма с подтверждением для новых учетных записей, я должен был создать собственный ApplicationUserManager и зарегистрировать его так, что он будет создан для каждого запроса:Пользовательский UserManager недоступен в OAuthAuthorizationServerProvider

public class IdentityConfig{ 
    public static void Initialize(IAppBuilder app) 
    { 
     [snip] 
     app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create); 
    } 

Он правильно работает внутри ApiController как это:

public class AccountController : ApiController 
{ 
    public ApplicationUserManager UserManager 
    { 
     get 
     { 
      return HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>(); 
     } 
    } 

проблема я столкнулся в том, что метод ApplicationUserManager.Create не вызывается, прежде чем я пытаюсь получить доступ к нему в методе создания OAuth маркеров:

public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider 
{ 
    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 
    { 
     var mgr = HttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>(); 

В приведенном выше коде mgr имеет значение null, потому что GetUserManager получает нуль

Является ли метод создания токена каким-то образом ранее в конвейере, так что методы CreatePerOwinContext еще не вызваны? Если да, то каков наилучший способ кэширования ApplicationUserManager, чтобы он мог использоваться внутри GrantResourceOwnerCredentials?

ответ

14

Это было сложно. Оказывается, код запуска должен выполняться в определенном порядке.

Этот код будет работать.

public class IdentityConfig{ 
    public static void Initialize(IAppBuilder app) 
    { 
     // correct... first create DB context, then user manager, then register OAuth Provider 
     app.CreatePerOwinContext(AuthContext.Create); 
     app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create); 

     OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions() 
     { 
      AllowInsecureHttp = true, 
      TokenEndpointPath = new PathString("/token"), 
      AccessTokenExpireTimeSpan = TimeSpan.FromDays(1), 
      Provider = new SimpleAuthorizationServerProvider() 
     }; 
     app.UseOAuthAuthorizationServer(OAuthServerOptions); 
     app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); 
    } 
} 

Если вы изменили порядок регистрации кода с помощью приложения, вы можете получить непреднамеренные последствия. Этот код вызывает ApplicationUserManager утратившими внутри метода GrantResourceOwnerCredentials маркера поколения

// wrong... these two lines must be after the ApplicationUserManager.Create line 
app.UseOAuthAuthorizationServer(OAuthServerOptions); 
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); 

[snip] 

app.CreatePerOwinContext(AuthContext.Create); 
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create); 

В то время как я на него, вот еще одна вещь, которая может срабатывать кого-то. Эти строки вызывают AuthContext утратившее внутри метод GrantResourceOwnerCredentials маркеров поколения

// wrong... The AuthContext must be instantiated before the ApplicationUserManager 
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create); 
app.CreatePerOwinContext(AuthContext.Create); 

[snip] 

app.UseOAuthAuthorizationServer(OAuthServerOptions); 
app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); 
4

Не используйте HttpContext.Current.GetOwinContext() в GrantResourceOwnerCredentials, как у вас уже есть контекст: (OAuthGrantResourceOwnerCredentialsContext context)

Вместо этого:

var mgr = context.OwinContext.GetUserManager<ApplicationUserManager>(); 

CreatePerOwinContext создается для каждого запроса, так что вы должны быть в состоянии принести объект ApplicationUserManager , Его следует называть немедленно, по телефону Startup. Возможно, ваша реализация запуска неверна. Я написал ответ here с некоторыми деталями для реализации.

+0

Я тоже пытался context.OwinContext, но это не помогло. Вы были на правильном пути, что это как-то связано с кодом запуска. Код запуска должен выполняться в определенном неочевидном порядке. Спасибо за подсказку, которая привела меня к ответу. – Brian

+0

Должен ли я распоряжаться 'UserManager' где-то в моей реализации' OAuthAuthorizationServerProvider'? – Shimmy

+1

@Shimmy: В этом не должно быть необходимости. 'UserManager' реализует' IDisposable' и 'CreatePerOwinContext' регистрирует объект только для запроса. – LeftyX

1

Вы также можете получить нуль возвращается, когда прошу OwinContext для ApplicationUserManager если app.UseWebApi(config); линия перед установкой OAuth.

Ниже будет вызывать большинство вызововHttpContext.Current.GetOwinContext().GetUserManager<ApplicationUserManager>();

вернуть нуль.

 HttpConfiguration config = new HttpConfiguration(); 

     WebApiConfig.Register(config); 
     app.UseWebApi(config); <-- Bad location 

     OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions() 
     { 
      AllowInsecureHttp = true, 
      TokenEndpointPath = new PathString("/token"), 
      AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30), 
      Provider = new ApplicationOAuthProvider("clientId"), 
      RefreshTokenProvider = new SimpleRefreshTokenProvider() 
     }; 

     app.UseOAuthAuthorizationServer(OAuthServerOptions); 
     app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); 
     app.UseOAuthBearerTokens(OAuthOptions); 

Перемещение app.UseWebApi(config); ниже приложения.Методы UseOAuth позволят вам получить ApplicationUserManager из OwinContext.

Это работает для меня:

 HttpConfiguration config = new HttpConfiguration(); 
     WebApiConfig.Register(config); 

     OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions() 
     { 
      AllowInsecureHttp = true, 
      TokenEndpointPath = new PathString("/token"), 
      AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30), 
      Provider = new ApplicationOAuthProvider("clientId"), 
      RefreshTokenProvider = new SimpleRefreshTokenProvider() 
     }; 

     app.UseOAuthAuthorizationServer(OAuthServerOptions); 
     app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions()); 
     app.UseOAuthBearerTokens(OAuthOptions); 

     app.UseWebApi(config); // <- Moved 
+0

Итак, вы имеете в виду все операции запуска идентификации перед выполнением инициализации веб-API? – Brian

+0

Я переформулирую ответ, он был плохо сформулирован. У меня была та же проблема, но ваш принятый ответ привел меня к моему решению. Для меня, все вызовы:. 'HttpContext.Current.GetOwinContext() GetUserManager ();' бы возвращать нулевое значение, если у меня был 'app.UseWebApi (конфигурации),' до моего приложения. Использовать вызовыOAuth. Перемещение 'app.UseWebApi (config);' после того, как моя настройка OAuth вызывает вызов GetUserManager , чтобы затем работать. Чтобы ответить на ваш вопрос напрямую, да, это заставило меня работать. –

+0

Делает чувство Чад. Спасибо за обновление. – Brian

Смежные вопросы