我有一个 ASP.NET MVC 5 应用程序,它使用 ASP.NET Identity 2.0 进行用户身份验证。
目前,用户在每次登录尝试时都必须输入验证码,但这引起了许多关于身份验证复杂性的提示。
主要目标是让人类登录尽可能简单,让机器人登录尽可能复杂。
我决定在一定次数的登录尝试失败后显示验证码。有many already asked questions关于它,但我没有找到可以帮助我构建相当完整的解决方案的答案。 我找到了这个question关于跟踪失败的尝试,但它也使用锁定,这不是我想要的。并根据this答案部分所需功能在旧的 ASP.NET 成员资格提供程序中可用,但在 ASP.NET Identity 中不可用(还?)。
因此,我最终得到了以下简化算法:
- 如果提供的登录名和密码对正确,则让用户登录。
- 如果登录名或密码不正确,则记录失败的登录尝试。
- 如果记录了用户的三次失败登录尝试,则显示带有验证码的登录页面。
- 如果输入的验证码有效,则刷新失败登录尝试的计数,然后转到 1。
- 如果输入的验证码无效,则再次显示验证码登录页面。
问题是:如何区分传入请求和特定登录请求?
我不能依赖 cookie、 session 、IP 等,因为任何机器人都可以更改它们。而且我也不能依赖登录,因为登录可能不完全存在。明显的方法是创建一个单独的表来存储登录、失败尝试计数和时间戳,但机器人可以轻松地用假登录淹没它,尽管我可以通过删除计划作业中的旧条目来解决此问题。
这是有效的解决方案吗?有更好的方法吗?
最佳答案
身份框架有每个用户登录失败的计数。您可以通过 await UserManager.AccessFailedAsync(userId)
来增加它。属性 ApplicationUser.AccessFailedCount
存储用户记录的失败计数。要重置失败计数,请调用 await UserManager.ResetAccessFailedCountAsync(userId)
因此可以利用这一点。
但是,这不计入无效用户名 - 数据库中不存在用户的登录尝试。对于这种情况,您可以使用建议的表并通过 cron-task 定期清除记录。
但是,如果用户尝试登录并每次尝试都输入不同的用户名,则此方法将会失败。所以无论如何我都会在那里放一个 cookie,但不要过分依赖它,因为我知道它很容易被杀死。
另一个解决方案是使用新的 Google reCaptcha - 在每一页上。然而,这是一项新技术,there are reports它并不完全可靠。
关于asp.net-mvc - N次登录失败后如何显示验证码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27646399/