如何注入 UserManager &登录管理器 [英] How to inject UserManager & SignInManager

查看:34
本文介绍了如何注入 UserManager &登录管理器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想弄清楚如何注入 UserManager 和 SignInManager.我已经在我的应用程序中安装了 Ninject,我正在以下列方式使用它:

I am trying to figure out how to inject UserManager and SignInManager. I have installed Ninject in my application and I am using it in the following manner:

请将此视为一个全新的项目.在 Startup.cs 中,我有以下内容:

Please consider this to be a brand new project. Inside Startup.cs I have the following:

public partial class Startup
{
    public void Configuration(IAppBuilder app)
    {
        ConfigureAuth(app);

        app.UseNinjectMiddleware(CreateKernel);
    }

    private static IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Load(Assembly.GetExecutingAssembly());


        return kernel;
    }
}

现在,如果我要创建一些 Dummy 类并尝试根据其有效的接口注入它.我已经测试过了.我想弄清楚的是我现在如何从 Startup.Auth.cs 中删除以下内容并注入它.没有我可以依赖的接口,我不确定这是如何完成的:

now if I were to create some Dummy class and try to inject it based on its interface that works. I have tested it. What I am trying to figure out is how would I now strip out the following out of Startup.Auth.cs and inject it. Having no interfaces I can rely on, I am not sure how this is done:

app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

再澄清一次,我的问题是:如何实例化 ApplicationUserManager 和 ApplicationSignInManager 并将其注入我的控制器参数中.这是我试图将其注入的控制器:

Just to clarify one more time, my question is: How do I instantiate ApplicationUserManager and ApplicationSignInManager and inject it in my controller parameters. Here is the controller that I am trying to inject this into:

public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager)
{
    UserManager = userManager;
    SignInManager = signInManager;
}

这是我尝试过的:

private static IKernel CreateKernel()
{
    var kernel = new StandardKernel();
    kernel.Load(Assembly.GetExecutingAssembly());

    kernel.Bind<IUserStore<ApplicationUser>>().To<UserStore<ApplicationUser>>();
    kernel.Bind<UserManager<ApplicationUser>>().ToSelf();

    return kernel;
}

但是有了这个,我得到了空引用错误

But with this I get null reference error

推荐答案

为了准确回答我的问题,这里是代码和说明:

To give an exact answer to what my question stated, here is the code and instructions:

第 1 步:创建自定义用户存储

Step 1: Create custom User Store

public class ApplicationUserStore : UserStore<ApplicationUser>
{
    public ApplicationUserStore(ApplicationDbContext context)
        : base(context)
    {
    }
}

第 2 步:更新 ApplicationUserManager 并将代码从 Create 方法移动到构造函数中

Step 2: Update ApplicationUserManager and move code from Create method into constructor

public class ApplicationUserManager : UserManager<ApplicationUser>
{
    public ApplicationUserManager(IUserStore<ApplicationUser> store, IdentityFactoryOptions<ApplicationUserManager> options)
        : base(store)
    {
        this.UserValidator = new UserValidator<ApplicationUser>(this)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };

        // Configure validation logic for passwords
        this.PasswordValidator = new PasswordValidator
        {
            RequiredLength = 6,
            RequireNonLetterOrDigit = true,
            RequireDigit = true,
            RequireLowercase = true,
            RequireUppercase = true,
        };

        // Configure user lockout defaults
        this.UserLockoutEnabledByDefault = true;
        this.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
        this.MaxFailedAccessAttemptsBeforeLockout = 5;

        // 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 it in here.
        this.RegisterTwoFactorProvider("Phone Code", new PhoneNumberTokenProvider<ApplicationUser>
        {
            MessageFormat = "Your security code is {0}"
        });
        this.RegisterTwoFactorProvider("Email Code", new EmailTokenProvider<ApplicationUser>
        {
            Subject = "Security Code",
            BodyFormat = "Your security code is {0}"
        });
        this.EmailService = new EmailService();
        this.SmsService = new SmsService();
        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            this.UserTokenProvider =
                new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
    }
}

第 3 步:修改Startup.Auth类,注释掉以下代码

Step 3: Modify the Startup.Auth class and comment out the following code

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

第 4 步:更新帐户控制器(或任何其他有问题的控制器)并添加以下构造函数

Step 4: Update Account Controller (or any other controller in question) and add the following constructor

public AccountController(ApplicationUserManager userManager, ApplicationSignInManager signInManager, IAuthenticationManager authManager)
{
    _userManager = userManager;
    _signInManager = signInManager;
    _authManager = authManager;
}

第 5 步:更新帐户控制器并使属性仅可检索:

Step 5: Update Account Controller and make properties only retrivable as so:

public ApplicationSignInManager SignInManager
{
    get
    {
        return _signInManager;
    }
}

public ApplicationUserManager UserManager
{
    get
    {
        return _userManager;
    }
}

private IAuthenticationManager AuthenticationManager
{
    get
    {
        return _authManager;
    }
}

第 6 步:更新 Startup.cs

Step 6: Update Startup.cs

public partial class Startup
{
    private IAppBuilder _app;
    public void Configuration(IAppBuilder app)
    {
        ConfigureAuth(app);
        _app = app;
        app.UseNinjectMiddleware(CreateKernel);
    }

    private IKernel CreateKernel()
    {
        var kernel = new StandardKernel();
        kernel.Load(Assembly.GetExecutingAssembly());

        kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
        kernel.Bind<IUserStore<ApplicationUser>>().To<ApplicationUserStore>();
        kernel.Bind<ApplicationUserManager>().ToSelf();
        kernel.Bind<ApplicationSignInManager>().ToSelf();
        kernel.Bind<IAuthenticationManager>().ToMethod(x => HttpContext.Current.GetOwinContext().Authentication);
        kernel.Bind<IDataProtectionProvider>().ToMethod(x => _app.GetDataProtectionProvider());

        return kernel;
    }
}

根据我收到的评论进一步扩展这个问题的答案:

To further expand the answer to this question, based on the comments I have received:

这些管理器不应该作为类注入,因为那样你就没有完成 DI.应该做的是创建多个接口,根据您的需要进一步分离和分组 UserManager 的方法.下面是一个例子:

These managers should not be injected as classes as then you are not accomplishing DI. What should be done instead is create multiple interfaces that further separate and group methods of UserManager according to your needs. Here is an example:

public interface IUserManagerSegment
{
    Task<IdentityResult> CreateAsync(ApplicationUser user, string password);
    Task<IdentityResult> CreateAsync(ApplicationUser user);
    Task<IdentityResult> ConfirmEmailAsync(string userId, string token);
    Task<ApplicationUser> FindByNameAsync(string userName);
    Task<bool> IsEmailConfirmedAsync(string userId);
    Task<IdentityResult> ResetPasswordAsync(string userId, string token, string newPassword);
    Task<IList<string>> GetValidTwoFactorProvidersAsync(string userId);
    Task<IdentityResult> AddLoginAsync(string userId, UserLoginInfo login);
    void Dispose(bool disposing);
    void Dispose();
}

上面的方法列出了一些我选择的随机方法,只是为了说明这一点.话虽如此,我们现在将基于这样的接口注入方法:

The above method has a list of few random methods I chose just to illustrate the point. With this said, we would now inject the method based on the interface such as this:

kernel.Bind<IUserManagerSegment>().To<ApplicationUserManager>();

现在我们的 AccountController 构造函数看起来像这样:

And now our AccountController constructor would look like this:

public AccountController(IUserManagerSegment userManager, ApplicationSignInManager signInManager, IAuthenticationManager authManager)  
{
    _userManager = userManager;
    _signInManager = signInManager;
    _authManager = authManager;
}

应该对 SignInManager 和 AuthenticationManager 做同样的事情.

Same thing should be done to SignInManager and AuthenticationManager.

上面的代码已经过测试并且可以正常工作.只需确保您已引用以下 DLL:

The code above has been tested and is working. Just ensure you have referenced the following DLLs:

Ninject.dll
Ninject.Web.Common
Ninject.Web.Common.OwinHost
Ninject.Web.Mvc

Ninject.dll
Ninject.Web.Common
Ninject.Web.Common.OwinHost
Ninject.Web.Mvc

这篇关于如何注入 UserManager &amp;登录管理器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆