【问题标题】:ASP.Net Identity 2.0 AccessFailedCount not incrementingASP.Net Identity 2.0 AccessFailedCount 不递增
【发布时间】:2014-06-13 14:12:12
【问题描述】:

昨晚我正在使用 FormsAuthentication 开发一个新项目,并且正在自定义票证以包含安全令牌,因此如果用户在一个浏览器中注销,它会在所有浏览器中注销。在查看 ASP.net Identity 的最新迭代时,它似乎已经内置了这个功能。

我创建了一个启用了个人帐户的新测试 MVC 5 Web 应用程序。注册和身份验证开箱即用。

但是,我注意到失败的登录尝试并没有增加 AspNetUsers 表中的 AccessFailedCount 字段。而且由于这并没有增加,我可以尝试尽可能多的失败登录尝试,而不会锁定帐户。

如何在 ASP.net Identity 2.0 上启用 AccessFailedCount 和 Lockout 功能?

【问题讨论】:

    标签: c# asp.net asp.net-mvc authentication asp.net-identity


    【解决方案1】:

    您必须手动处理。 CheckPassword 方法调用PasswordHasher.VerifyHashedPassword 方法验证密码,但当提供的密码与现有密码不匹配时,它不会更新访问失败计数。

    下面是一个支持锁定的验证方法示例:

    UserManager<User> userManager = new UserManager<User>(new UserStore());
    
    if (userManager.SupportsUserLockout && userManager.IsLockedOut(userId))
        return;
    
    var user = userManager.FindById(userId);
    if (userManager.CheckPassword(user, password))
    {
        if (userManager.SupportsUserLockout && userManager.GetAccessFailedCount(userId) > 0)
        {
            userManager.ResetAccessFailedCount(userId);
        }
    
        // Authenticate user
    }
    else
    {
        if (userManager.SupportsUserLockout && userManager.GetLockoutEnabled(userId))
        {
            userManager.AccessFailed(userId);
        }
    }
    

    【讨论】:

    • 谢谢,我希望这不是手动过程。由于所有分散的配置、泄漏的抽象以及您必须手动实现的东西,我很难看到 ASP.net Identity 相对于旧的 FormsAuthentication 系统的价值(除非您使用的是外部身份验证提供程序)。
    • 2.1 版中的SignInManager 将提供更高级别的PasswordSignIn API,该API 隐藏了很多关于锁定/双因素等的复杂性。
    • 果然如@HaoKung所说,在我刚开始新项目的v2.2.1中,有var result = await SignInManager.PasswordSignInAsync(model.UserName, model.Password, model.RememberMe, shouldLockout: false);这一行只需将false更改为true,对于那些登陆的人像我一样在这里,需要这个。
    • 如果调用AccessFailed也没有迭代AccessFailedCountSupportsUserLockout是真的怎么办?
    • 是的,我们曾经有自己的 asp.net 2.X 身份验证和授权实现来克服 Web 表单默认身份验证的相当大的失败......我很惊讶地发现 asp 有这么多问题.net 身份这么多年过去了。 MS 找不到一些像样的开发者吗?
    【解决方案2】:

    还有接受“shouldLockout”参数的 PasswordSignInAsync。将此设置为 true 将自动增加失败的登录尝试次数

    var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: true);
    

    【讨论】:

    • 如果用户成功登录,您似乎仍然需要调用 ResetAccessFailedCountAsync()。不知道为什么该代码不在默认项目模板中。
    • 请注意,AccessFailed 在“失败”周期结束时重置为 0。一旦达到最大尝试次数,AccessFailed 将重置为 0 并再次设置 LockoutEndDateUtc。您只能访问每个 fail 周期内的失败尝试次数。
    • @JoelB 这是现在的默认行为(至少在 2.2 中)。
    【解决方案3】:

    对于 .NET Core 2.1,shouldLockout 现在被命名为 lockoutOnFailure

    因此,您的登录调用应如下所示,以增加失败的登录尝试:

    var result = await SignInManager.PasswordSignInAsync(loginModel.Email, loginModel.Password, loginModel.RememberMe, lockoutOnFailure: true);
    

    一旦用户成功登录,这也会重置失败的登录尝试。

    【讨论】:

      猜你喜欢
      • 2018-06-03
      • 2014-12-14
      • 2015-02-09
      • 2014-12-25
      • 2014-11-13
      • 2015-08-09
      • 2014-05-15
      • 1970-01-01
      • 2014-06-06
      相关资源
      最近更新 更多