如何在IdentityServer DI框架中注册ApplicationUserManager?

时间:2017-03-02 18:54:38

标签: asp.net-identity asp.net-identity-2 identityserver3

我使用IdentityServer3进行身份验证。所有用户都存储在Sql DB中,因此我也使用Microsoft.AspNet.Identity框架进行实际身份验证,出于同样的目的,我创建了自己的ApplicationUserManager类。

AspNet标识具有集成到OWIN中间件中的IoC功能。它注册了ApplicationUserManager,如:

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

它需要函数委托,它返回ApplicationUserManager

的新实例
public static ApplicationUserManager 
Create(IdentityFactoryOptions<ApplicationUserManager> options,
        IOwinContext context)
    {
        var manager = new ApplicationUserManager(new UserStore<ApplicationUser>(context.Get<ApplicationDbContext>()));

但是,IdentityServer使用自己的DI框架和(我认为)我们不能使用静态Create()方法与IdentityServer一起使用ApplicationUserManager,同样Create()方法将IdentityFactoryOptionsIOwinContext作为参数。

我遵循了这个SO post并且我改变了ApplicationUserManager的实现以使用构造函数注入

public class ApplicationUserManager : UserManager<ApplicationUser, string>
{   
    public ApplicationUserManager(ApplicationUserStore store, IdentityFactoryOptions<ApplicationUserManager> options)
        : base(store)
    {          
        // Configure validation logic for usernames
        UserValidator = new UserValidator<ApplicationUser>(this)
        {
            AllowOnlyAlphanumericUserNames = false,
            RequireUniqueEmail = true
        };

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

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

        EmailService = new EmailService();
        SmsService = new SmsService();

        var dataProtectionProvider = options.DataProtectionProvider;
        if (dataProtectionProvider != null)
        {
            UserTokenProvider =
                new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("ASP.NET Identity"));
        }
    }        
}

然后使用IdentityServer自己的DI框架注册所有服务,如下所示

factory.UserService = new Registration<IUserService, UserService>();
factory.Register(new Registration<ApplicationUserManager>());
factory.Register(new Registration<ApplicationUserStore>());
factory.Register(new Registration<IdentityFactoryOptions<ApplicationUserManager>>(resolver => new IdentityFactoryOptions<ApplicationUserManager>
            {
                DataProtectionProvider = new Microsoft.Owin.Security.DataProtection.DpapiDataProtectionProvider("ASP.NET Identity")
            }));
factory.Register(new Registration<ApplicationDbContext>(resolver => new ApplicationDbContext(ApplicationConfig.ConnectionString)));

问题

  1. 这是注册ApplicationUserManager的正确方法吗? IdentiServer的DI框架?
  2. 我在注册过程中创建DataProtectionProvider,在构造函数中创建UserTokenProvider。 IdentityServer如何使用这2个提供程序?
  3. 请注意,我从未在任何地方注册IOwinContext 将来,ApplicationUserManager的构造函数不再需要它了 导致OWIN管道出现任何问题?
  4. ApplicationUserManager
  5. 的理想注册模式是什么?

1 个答案:

答案 0 :(得分:3)

这两篇文章有助于解决我的问题

http://tech.trailmax.info/2014/06/asp-net-identity-and-cryptographicexception-when-running-your-site-on-microsoft-azure-web-sites/

http://tech.trailmax.info/2014/09/aspnet-identity-and-ioc-container-registration/

但是我的ApplicationUserManager位于单独的类库中,startup.cs位于Web项目中。类库没有引用Web项目。所以我重构了ApplicationUserManager构造函数

    public ApplicationUserManager(ApplicationUserStore store, IDataProtectionProvider dataProtectionProvider)
        : base(store)
    {
       // other stuff


        if (dataProtectionProvider != null)
        {
            UserTokenProvider =
                new DataProtectorTokenProvider<ApplicationUser>(dataProtectionProvider.Create("UserToken"));
        }
    }

并注册了IDataProtectionProvider DI框架。我没有将Unity用作IoC。我正在使用IdentityServer自己的DI框架。所以我将IDataProtectionProvider注册为

  factory.Register(new Registration<IDataProtectionProvider>(resolver => Startup.DataProtectionProvider));