У меня возникают проблемы с созданием пользовательского UserStore с использованием инъекции зависимостей при создании ApplicationUserManager с использованием конвейера запросов OWIN.
Фон
Я пытаюсь перенести пользовательские функции в нашем веб-приложении с помощью SimpleMembership на новую идентификацию ASP.NET. При запуске нового проекта MVC 5 стандартная реализация одностраничного приложения использует ASP.Identity, используя Entity Framework для реализации функций UserStore.
В моем случае мы уже используем NHibernate в качестве ORM и используем ninject для реализации единицы шаблона работы, так что у нас был один сеанс NHibernate для каждого запроса, и я хотел сделать работу ASP.Identity с нашей существующей структурой.
С этой целью я создал пользовательский UserStore, который можно было создать, введя соответствующий сеанс репозиториев /nhibernate и т.д. Затем его можно было бы ввести в конструктор Controller с использованием Ninject, а не использовать функциональность GetOwinContext по умолчанию.
Чтобы сделать это, я прокомментировал следующую строку в приложении ConfigureAuth (IAppBuilder) для Startup, который по умолчанию создает класс UserManager:
// app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
Вместо этого я использовал NinjectWebCommon, созданный при установке пакета Ninject.Web.Common.Webhost nuget для создания соответствующих привязок.
Эта реализация отлично работала с некоторыми операциями UserManager, но с некоторыми операциями, такими как ResetPasswordAsync, она терпит неудачу, потому что реализация по умолчанию ApplicationUserManager не вызывается, поэтому UserTokenProvider в классе UserManager никогда не устанавливается:
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));
// Configure validation logic for usernames
manager.UserValidator = new UserValidator<ApplicationUser>(manager)
{
AllowOnlyAlphanumericUserNames = false,
RequireUniqueEmail = true
};
// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
RequiredLength = 6,
RequireNonLetterOrDigit = true,
RequireDigit = true,
RequireLowercase = true,
RequireUppercase = true,
};
// Register two factor authentication providers. This application uses Phone and Emails as a step of receiving a code for verifying the user
// You can write your own provider and plug in here.
manager.RegisterTwoFactorProvider("PhoneCode", new PhoneNumberTokenProvider<ApplicationUser>
{
MessageFormat = "Your security code is: {0}"
});
manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider<ApplicationUser>
{
Subject = "Security Code",
BodyFormat = "Your security code is: {0}"
});
manager.EmailService = new EmailService();
manager.SmsService = new SmsService();
var dataProtectionProvider = options.DataProtectionProvider;
if (dataProtectionProvider != null)
{
manager.UserTokenProvider = new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
}
return manager;
}
Следовательно, UserTokenProvider не установлен.
Проблема
Я хочу использовать конвейер OWIN, потому что реализация Visual Studio по умолчанию класса ApplicationUserManager вводит IDataProtectionProvider в свой метод обратного вызова Create. Однако я также хочу создать свой UserStore с использованием зависимостей Injection, и я не знаю, как создать UserStore в этом методе с использованием инъекции зависимостей.
public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
// WANT TO CREATE THE USER STORE USING NINJECT DEPENDENCY INJECTION HERE
// var userStore = ...
var manager = new ApplicationUserManager(userStore);
}
Я попытался обойти это ограничение, используя пакет Ninject.Web.Common.OwinHost nuget и создав ядро в классе Startup.
public void ConfigureAuth(IAppBuilder app)
{
// Setup
app.UseNinjectMiddleware(CreateKernel);
}
Тем не менее, Ninject.Web.Common.OwinHost не раскрывает свое ядро, поэтому я не могу использовать шаблон местоположения службы, чтобы вставлять значения в мой пользовательский UserStore в обратном вызове Create.
Я также попытался создать одноэлементное ядро и зарегистрировать его с помощью app.CreatePerOwinContext(CreateKernel) с соответствующим делегатом, чтобы позже получить доступ к ядру, но когда я вызываю context.Get(), он просто возвращает null.
Вопрос
Как я могу зарегистрировать функцию обратного вызова с помощью CreatePerOwinContext для создания пользовательского UserManager, который использует пользовательский UserStore, а затем использовать Ninject для создания пользовательского UserStore с использованием инъекции зависимостей в обратном вызове Create, так что у меня также есть доступ к IdentityFactoryOptions, который Owin использует для ввода поставщика токенов пользователя?