gpt4 book ai didi

c# - 使用 Ninject OWIN 中间件在 OWIN 启动中依赖注入(inject) UserStore

转载 作者:IT王子 更新时间:2023-10-29 03:59:11 28 4
gpt4 key购买 nike

在使用 OWIN 请求管道创建 ApplicationUserManager 时,我在使用依赖注入(inject)创建自定义 UserStore 时遇到问题。

背景

我正在尝试将 Web 应用程序中的用户功能从使用 SimpleMembership 迁移到新的 ASP.NET Identity。当开始一个新的 MVC 5 项目时,单页应用程序的默认实现使用 ASP.Identity,使用 Entity Framework 来实现 UserStore 功能。

在我的例子中,我们已经使用 NHibernate 作为 ORM,并使用 ninject 来实现工作单元模式,这样我们每个请求都有一个 NHibernate session ,我想让 ASP.Identity 与我们现有的框架一起工作.

为此,我创建了一个自定义 UserStore,它可以通过注入(inject)相关的存储库/nhibernate session 等来创建。然后可以使用 Ninject 将其注入(inject)到 Controller 的构造函数中,而不是使用默认实现的 GetOwinContext 功能。

为了做到这一点,我在默认情况下创建 UserManager 类的 Startup 的 ConfigureAuth(IAppBuilder app) 方法中注释掉了以下行:

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

相反,我使用在安装 Ninject.Web.Common.Webhost nuget 包时创建的 NinjectWebCommon 来创建相关绑定(bind)。

此实现在某些 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 回调方法中注入(inject)了 IDataProtectionProvider。但是,我还想使用依赖注入(inject)创建我的 UserStore,但我不知道如何使用依赖注入(inject)在此方法中创建 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 不公开其内核,因此我无法使用服务定位模式在创建回调中将值注入(inject)我的自定义 UserStore。

我还尝试创建一个单例内核,并使用 app.CreatePerOwinContext(CreateKernel) 向相关委托(delegate)注册它,这样我以后可以访问内核,但是当我调用 context.Get() 时,它只返回 null。

问题

如何使用 CreatePerOwinContext 注册回调函数以创建使用自定义 UserStore 的自定义 UserManager,然后使用 Ninject 在 Create 回调中使用依赖注入(inject)创建自定义 UserStore,这样我也可以访问 IdentityFactoryOptions Owin 用于注入(inject)用户 token 提供程序?

最佳答案

信息:

可以将内核注册为单例,以便 ninject 中间件可以使用同一个内核,并且还可以在 owin 上下文中注册。

    public static StandardKernel CreateKernel()
{
if (_kernel == null)
{
_kernel = new StandardKernel();
_kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();

_kernel.Load(Assembly.GetExecutingAssembly(), Assembly.Load("Super.CompositionRoot"));
}
return _kernel;
}

回调函数 app.CreatePerOwinContext(ApplicationUserManager.Create) 将调用 ApplicationUserManager.Create 而不是将其注册为稍后在设置期间调用。因此,需要在 ApplicationUserManager 的 Create 回调之前注册 CreateKernel 函数,否则如果您尝试从该方法中的 owin 上下文中获取内核,则会出现空引用异常。

    public void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext(CreateKernel);
app.UseNinjectMiddleware(CreateKernel);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
}

这将允许您访问内核以在 ApplicationUserManager 的创建回调中创建自定义 UserStore:

    public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context)
{
var kernel = context.Get<StandardKernel>();
var userStore = kernel.Get<IUserStore<User, int>>();
var manager = new ApplicationUserManager(userStore);
//...
}

我知道在一般情况下依赖注入(inject)应该比服务定位更受青睐,但在这种情况下我看不出解决它的方法 - 除非有人有任何更好的建议?

这将允许您使用 Ninject 来实现利用 Ninject 的 InRequestScope().OnDeactivation 功能的工作单元模式。我知道 UserManager 类有一个 per request lifetime ,但不知道在请求完成时提交任何未完成事务的最合适方法。

关于c# - 使用 Ninject OWIN 中间件在 OWIN 启动中依赖注入(inject) UserStore,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24373311/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com