CQRS学习——集成ASP.NET Identity[其五]

【其实和Cqrs没啥关系】

缘由

其实没啥原因,只是觉得以前写了不知多少遍的用户登录复用性太差,实现的功能也不多。

依赖的Nuget包

简单登陆

就简单登陆而言,只需要实现如下接口/抽象类:

Store相关:

IUserLockoutStore<DpfbUser,Guid> , IUserPasswordStore<DpfbUser,Guid>,  IUserTwoFactorStore<DpfbUser,Guid>, IUserEmailStore<DpfbUser,Guid>

Manager相关:

UserManager<DpfbUser, Guid>, SignInManager<DpfbUser, Guid>

打包的代码:

    public class AppSignInManager : SignInManager<DpfbUser, Guid>
    {
        public AppSignInManager()
            : base(WebContextHelper.CurrentOwinContext.Get<AppUserManager>(),
                WebContextHelper.CurrentOwinContext.Authentication)
        {

        }

        public override async Task<ClaimsIdentity> CreateUserIdentityAsync(DpfbUser user)
        {
            var userIdentity = await UserManager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie);
            return userIdentity;
        }
    }

public class AppUserManager : UserManager<DpfbUser, Guid>
    {
        public AppUserManager(DpfbUserStore store)
            : base(store)
        {

        }

        public AppUserManager()
            : this(WebContextHelper.CurrentOwinContext.Get<DpfbUserStore>())
        {

        }
    }

public class DpfbUserStore : 
        //IUserStore<DpfbUser, Guid>, 
        IUserLockoutStore<DpfbUser, Guid>,
        IUserPasswordStore<DpfbUser,Guid>,
        IUserTwoFactorStore<DpfbUser,Guid>,
        IUserEmailStore<DpfbUser,Guid>
    {
        [Dependency]
        internal IDpfbUserQueryEntry UserQueryEntry
        {
            get { return CqrsConfigurationResolver.Config.Construct<IDpfbUserQueryEntry>(); }
        }

        internal ICommandBus CommandBus
        {
            get { return CqrsConfigurationResolver.CommandBus; }
        }

        public Task CreateAsync(DpfbUser user)
        {
            throw new NotImplementedException();
        }

        public Task DeleteAsync(DpfbUser user)
        {
            throw new NotImplementedException();
        }

        public Task<DpfbUser> FindByIdAsync(Guid userId)
        {
            return UserQueryEntry.TryFetchAsync(userId);
        }

        public Task<DpfbUser> FindByNameAsync(string userName)
        {
            return UserQueryEntry.TryFetchByNameAsync(userName);
        }

        public Task UpdateAsync(DpfbUser user)
        {
            //throw new NotImplementedException();
            return Task.FromResult(0);
        }

        public void Dispose()
        {
            //do nothing
        }

        public Task<DateTimeOffset> GetLockoutEndDateAsync(DpfbUser user)
        {
            //throw new NotImplementedException();
            return Task.FromResult(new DateTimeOffset(DateTime.Now));
        }

        public Task SetLockoutEndDateAsync(DpfbUser user, DateTimeOffset lockoutEnd)
        {
            //throw new NotImplementedException();
            return Task.FromResult(0);
        }

        public Task<int> IncrementAccessFailedCountAsync(DpfbUser user)
        {
            throw new NotImplementedException();
            return Task.FromResult(0);
        }

        public Task ResetAccessFailedCountAsync(DpfbUser user)
        {
            return Task.FromResult(0);
        }

        public Task<int> GetAccessFailedCountAsync(DpfbUser user)
        {
            return Task.FromResult(0);
            throw new NotImplementedException();
        }

        public Task<bool> GetLockoutEnabledAsync(DpfbUser user)
        {
            return Task.FromResult(false);
            throw new NotImplementedException();
        }

        public Task SetLockoutEnabledAsync(DpfbUser user, bool enabled)
        {
            return Task.FromResult(0);
            throw new NotImplementedException();
        }

        public Task SetPasswordHashAsync(DpfbUser user, string passwordHash)
        {
            CommandBus.Send(new SetPasswordHashCommand() {UserId = user.Id, PasswordHash = passwordHash});
            return Task.FromResult(0);
        }

        public Task<string> GetPasswordHashAsync(DpfbUser user)
        {
            return UserQueryEntry.FetchPasswordHashAsync(user.Id);
        }

        public Task<bool> HasPasswordAsync(DpfbUser user)
        {
            return UserQueryEntry.HasPasswordAsync(user.Id);
        }

        public Task SetTwoFactorEnabledAsync(DpfbUser user, bool enabled)
        {
            return Task.FromResult(false);
            throw new NotImplementedException();
        }

        public Task<bool> GetTwoFactorEnabledAsync(DpfbUser user)
        {
            return Task.FromResult(false);
            throw new NotImplementedException();
        }

        public Task SetEmailAsync(DpfbUser user, string email)
        {
            throw new NotImplementedException();
            return Task.FromResult(0);
        }

        public Task<string> GetEmailAsync(DpfbUser user)
        {
            throw new NotImplementedException();
        }

        public Task<bool> GetEmailConfirmedAsync(DpfbUser user)
        {
            throw new NotImplementedException();
            return Task.FromResult(true);
        }

        public Task SetEmailConfirmedAsync(DpfbUser user, bool confirmed)
        {
            throw new NotImplementedException();
            return Task.FromResult(0);
        }

        public Task<DpfbUser> FindByEmailAsync(string email)
        {
            throw new NotImplementedException();
        }
    }
View Code

配置

public partial class Startup
    {
        //配置Identity身份验证
        public void ConfigureAuth(IAppBuilder app)
        {
            app.CreatePerOwinContext(() => new DpfbUserStore());
            app.CreatePerOwinContext((IdentityFactoryOptions<AppUserManager> options,
                IOwinContext context) =>
            {
                var manager = new AppUserManager();

                //用户信息验证
                manager.UserValidator = new UserValidator<DpfbUser, Guid>(manager)
                {
                    AllowOnlyAlphanumericUserNames = false,
                    RequireUniqueEmail = false
                };

                //密码验证
                manager.PasswordValidator = new PasswordValidator
                {
                    RequiredLength = 6,
                    RequireNonLetterOrDigit = true,
                    RequireDigit = true,
                    RequireLowercase = true,
                    RequireUppercase = true,
                };

                //配置最大出错次数
                manager.UserLockoutEnabledByDefault = true;
                manager.DefaultAccountLockoutTimeSpan = TimeSpan.FromMinutes(5);
                manager.MaxFailedAccessAttemptsBeforeLockout = 5;

                //开启两步验证
                manager.RegisterTwoFactorProvider("PhoneCode", new PhoneNumberTokenProvider<DpfbUser, Guid>
                {
                    MessageFormat = "Your security code is: {0}"
                });
                manager.RegisterTwoFactorProvider("EmailCode", new EmailTokenProvider<DpfbUser, Guid>
                {
                    Subject = "SecurityCode",
                    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<DpfbUser, Guid>(dataProtectionProvider.Create("ASP.NET Identity"));
                }
                return manager;
            });
            app.CreatePerOwinContext(()=>new AppSignInManager());

            //配置Cookie
            app.UseCookieAuthentication(new CookieAuthenticationOptions
            {
                AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
                LoginPath = new PathString("/system/login"),
                Provider = new CookieAuthenticationProvider
                {
                    // Enables the application to validate the security stamp when the user logs in.
                    // This is a security feature which is used when you change a password or add an external login to your account.  
                    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<AppUserManager, DpfbUser, Guid>(
                        TimeSpan.FromMinutes(30),
                        (AppUserManager manager, DpfbUser user) =>
                            manager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie),
                        user => new Guid(user.GetUserId<string>()))
                }
            });
            app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

            // Enables the application to temporarily store user information when they are verifying the second factor in the two-factor authentication process.
            app.UseTwoFactorSignInCookie(DefaultAuthenticationTypes.TwoFactorCookie, TimeSpan.FromMinutes(5));

            // Enables the application to remember the second login verification factor such as phone or email.
            // Once you check this option, your second step of verification during the login process will be remembered on the device where you logged in from.
            // This is similar to the RememberMe option when you log in.
            app.UseTwoFactorRememberBrowserCookie(DefaultAuthenticationTypes.TwoFactorRememberBrowserCookie);
        }
    }
View Code

修改密码

AppUserManager的基类有个属性RequireUniqueEmail,当这个属性被置为true的时候,修改密码(以及其他敏感操作)会要求Email验证,对于内部系统而言,可以将这个属性置为false。

...

【加功能的时候再补充】

原文地址:https://www.cnblogs.com/lightluomeng/p/4922674.html