类似的问题:用户输入三次密码错误之后,如何限制用户十分钟内禁止登录?
首先我们要明确的就是在多次输错密码之后限制的是用户还是IP。
一般情况下建议使用IP地址为单位来进行限制,而非具体的用户,这样可以避免影响到真实用户的使用,减少误伤其他用户的可能性。
例如,一个非法用户拿着别人的账户不断尝试,或者其他用户在输错账户的情况下,不断尝试错误密码,如果直接将其限制登录了,那么账户本人也就无法登录自己的账户了。因此,以IP地址为单位来限制相对更加合理。
同时,以IP地址为单位进行限制还可以避免其他攻击行为,比如黑客通过使用同一IP地址进行暴力破解的攻击行为,也可以提供高系统的安全性和稳定性。
但实际情况下我们还要考虑不同场景下的策略调整、粒度控制等因素,以达到用户的最佳体验和安全性能的一个平衡。
使用Redis的常见做法
后台使用Redis记录当前IP尝试登录的次数:
- key为该IP请求登录的唯一标识
- value为当前IP的尝试登录次数
我们需要给这个key设置一个过期时间,用来实现指定时间内无法再次登录的效果,而不是永久无法登录。并且,每次key对应的value进行修改时,都需要重置过期时间。
整个逻辑也很简单(假设错误阈值为3):
- 当用户提交用户名和密码登录时,先哦按段是否有对应的key
- 如果没有对应key的话,说明是第一次登录,直接校验用户名和密码的正确性即可。用户名和密码校验通过,则返回登录成功;否则,就返回登陆失败,用户名/密码错误,并创建对应的key,key对应的值为1,代表其已经请求尝试登录过1次了。
- 如果有对应的key,说明不是第一次登录了,需要判断key对应的value大小是否小于3。
- 如果小于3则代表还能继续尝试登录,重复密码校验这一步。用户名和密码校验通过,则返回登录成功;否则,就返回登录失败,用户名/密码错误,并将key对应的value值+1(建议使用Lua脚本,涉及到get、incr、expire三个操作)。
- 如果value等于3,则表明IP已经尝试登录过三次,返回输入错误次数达到3次,请xx分钟后再尝试。
不使用Redis的常见做法
直接在用户表中增加两个字段
- 输错密码次数num
- 禁止登录的截至时间点lock-time
我们需要记录输错密码次数num,当输入正确密码后重置num和lock-time字段的值,当输错密码次数达到3次后,修改lock-time为允许再次登录的时间,
整个逻辑也很简单(假设错误阈值为3):
- 当用户提交用户名和密码登录时,先判断当前时间点是不是比lock-time小。
- 如果比lock-time小的话,说明当前用户暂时被限制登录,返回输入错误次数达到3次,请xx分钟后再尝试。
- 如果大于等于lock-time的话,表名当前未被限制登录,进一步判断num大小是否小于3。
- 如果小于3则代表还能继续尝试登录,用户名和密码校验通过,则返回登录成功,并重置num和lock-time字段值;否则,就返回登陆失败,用户名/密码错误,并将num的值+1。
- 如果num=3,则表明该IP已经尝试登录过3次,返回输入错误次数达到3次,请xx分钟后再尝试。