代码之家  ›  专栏  ›  技术社区  ›  jwatts1980

SignInManager未调用AccessFailed和Lockout方法

  •  0
  • jwatts1980  · 技术社区  · 8 年前

    我已经在一个asp.netcore2mvc应用程序中实现了用户存储。请参阅下面的实现代码。我已经设置了启动选项,并且 lockoutOnFailure: true 上 PasswordSignInAsync() 方法。

    由于某些原因,没有在用户存储上调用访问失败的方法。只调用“getLockoutenabledAsync()”。

    当前的实现对于常规登录非常有效。我可以在没有任何问题的情况下登录。但是当测试失败的登录时,我不确定我缺少了什么来让它正确使用锁定和失败计数。

    public class MyUser : IdentityUser<int>
    {
        //...
        //AccessFailedCount, LockoutEnd, and LockoutEnabled are apart of IdentityUser
        //...
    }
    
    public class AccountController : Controller
    {
        public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
        {
            //...
            var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: true);
            //...
        }
    }
    
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            //...
            services.AddIdentity<MyUser, MyRole>(a =>
            {
                //...
                a.Lockout.AllowedForNewUsers = true;
                a.Lockout.DefaultLockoutTimeSpan = new System.TimeSpan(0, 5, 0);
                a.Lockout.MaxFailedAccessAttempts = 5;
            })
            .AddDefaultTokenProviders()
            .AddSignInManager<SignInManager<MyUser>>()
            .AddUserStore<MyUserStore>()
            .AddRoleStore<MyRoleStore>();
            //...
        }
    }
    
    public class MyUserStore : IUserStore<MyUser>, IUserRoleStore<MyUser>,
        IUserPasswordStore<MyUser>, IUserEmailStore<MyUser>, IUserLockoutStore<MyUser>
    {
        //...
    
        #region IUserLockoutStore interface
    
        public async Task<DateTimeOffset?> GetLockoutEndDateAsync(MyUser user, CancellationToken cancellationToken)
        {
            if (user == null)
            {
                throw new ArgumentException("Cannot get lockout end date. User is null.");
            }
            return user.LockoutEnd;
        }
    
        public async Task SetLockoutEndDateAsync(MyUser user, DateTimeOffset? lockoutEnd, CancellationToken cancellationToken)
        {
            if (user == null)
            {
                throw new ArgumentException("Cannot set lockout end date. User is null.");
            }
    
            user.LockoutEnd = lockoutEnd;
        }
    
        public async Task<int> IncrementAccessFailedCountAsync(MyUser user, CancellationToken cancellationToken)
        {
            if (user == null)
            {
                throw new ArgumentException("Cannot update AccessFailedCount. User is null.");
            }
    
            user.AccessFailedCount += 1;
            return user.AccessFailedCount;
        }
    
        public async Task ResetAccessFailedCountAsync(MyUser user, CancellationToken cancellationToken)
        {
            if (user == null)
            {
                throw new ArgumentException("Cannot update AccessFailedCount. User is null.");
            }
    
            user.AccessFailedCount = 0;
        }
    
        public async Task<int> GetAccessFailedCountAsync(MyUser user, CancellationToken cancellationToken)
        {
            if (user == null)
            {
                throw new ArgumentException("Cannot get AccessFailedCount. User is null.");
            }
            return user.AccessFailedCount;
        }
    
        public async Task<bool> GetLockoutEnabledAsync(MyUser user, CancellationToken cancellationToken)
        {
            if (user == null)
            {
                throw new ArgumentException("Cannot get LockoutEnabled. User is null.");
            }
            return user.LockoutEnabled;
        }
    
        public async Task SetLockoutEnabledAsync(MyUser user, bool enabled, CancellationToken cancellationToken)
        {
            if (user == null)
            {
                throw new ArgumentException("Cannot set LockoutEnabled. User is null.");
            }
    
            user.LockoutEnabled = enabled;
        }
    
        #endregion
    }
    
    1 回复  |  直到 8 年前
        1
  •  0
  •   jwatts1980    8 年前

    这是不起作用的,因为我做错了什么事和一个错误(技术上2件事我做错了)。

    • 我用的是一个不存在的用户帐户(拼写错误,没有抓住它)。因为帐户访问是在基线用户管理器中处理的,所以我没有得到明确的消息传递。
    • 我也有一个与AutoPaPad的映射问题,我没有在身份用户和EF模型之间映射访问失败的计数。

    为了解决这个问题,我最终从github获得了身份代码( https://github.com/aspnet/Identity )并为signinmanager和usermanager创建“自定义”类,以便我可以单步执行代码。然后将它们临时添加到ioc容器中

        services.AddIdentity<MyUser, MyRole>(a =>
        {
            a.Password.RequiredLength = 10;
            a.Password.RequireLowercase = true;
            a.Password.RequireUppercase = true;
            a.User.AllowedUserNameCharacters = null;
            a.User.RequireUniqueEmail = true;
            a.Lockout.AllowedForNewUsers = true;
            a.Lockout.DefaultLockoutTimeSpan = new System.TimeSpan(0, 5, 0);
            a.Lockout.MaxFailedAccessAttempts = 5;
        })
            .AddDefaultTokenProviders()
            .AddSignInManager<MySignInManager>() //<-----
            .AddUserManager<MyUserManager>() //<-----
            .AddUserStore<MyUserStore>()
            .AddRoleStore<MyRoleStore>();