【发布时间】:2014-08-13 22:18:14
【问题描述】:
在使用 OWIN 请求管道创建 ApplicationUserManager 时,我在使用依赖注入创建自定义 UserStore 时遇到问题。
背景
我正在尝试将 Web 应用程序中的用户功能从使用 SimpleMembership 迁移到新的 ASP.NET 标识。在开始一个新的 MVC 5 项目时,单页应用程序的默认实现使用 ASP.Identity,使用 Entity Framework 来实现 UserStore 功能。
在我的例子中,我们已经使用 NHibernate 作为 ORM,并使用 ninject 来实现工作单元模式,这样我们每个请求都有一个 NHibernate 会话,我想让 ASP.Identity 与我们现有的框架一起工作.
为此,我创建了一个自定义 UserStore,它可以通过注入相关的存储库/nhibernate 会话等来创建。然后可以使用 Ninject 将其注入到 Controller 的构造函数中,而不是使用默认实现的 GetOwinContext 功能。
为了做到这一点,我在 Startup 的 ConfigureAuth(IAppBuilder app) 方法中注释掉了以下行,该方法默认创建 UserManager 类:
// app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
相反,我使用安装 Ninject.Web.Common.Webhost nuget 包时创建的 NinjectWebCommon 来创建相关绑定。
此实现在某些 UserManager 操作中运行良好,但在某些操作(例如 ResetPasswordAsync)中失败,因为未调用默认的 ApplicationUserManager 实现,因此从不设置 UserManager 类中的 UserTokenProvider:
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 类的默认实现在其 Create 回调方法中注入了 IDataProtectionProvider。但是,我也想使用依赖注入创建我的用户存储,我不知道如何使用依赖注入在此方法中创建用户存储。
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 没有公开其内核,因此我无法使用服务位置模式将值注入到 Create 回调中的自定义 UserStore。
我还尝试创建一个单例内核,并使用 app.CreatePerOwinContext(CreateKernel) 将其注册到相关委托,这样我以后可以访问内核,但是当我调用 context.Get() 时它只返回 null。
问题
如何使用 CreatePerOwinContext 注册回调函数以创建使用自定义 UserStore 的自定义 UserManager,然后使用 Ninject 在 Create 回调中使用依赖注入创建自定义 UserStore,这样我也可以访问 IdentityFactoryOptions Owin 用于注入用户令牌提供程序?
【问题讨论】:
标签: c# asp.net dependency-injection ninject owin