如何在MySQL中统计失败登录次数时忽略用户成功登录之前的所有记录?
解决登录失败次数统计的误封禁问题
咱们先明确核心需求:要统计用户30分钟内的失败登录次数,但必须忽略最近一次成功登录之前的所有失败记录——毕竟用户成功登录后,之前的失败尝试就应该被“清零”了,不能再拿来算入后续的封禁判断。
改进后的SQL语句
SELECT COUNT(usuario) AS cant FROM mo_bitacora WHERE d_accion = 'failed' AND f_registro BETWEEN (NOW() - INTERVAL 30 MINUTE) AND NOW() AND usuario = 'user' -- 只统计最近一次成功登录之后的失败记录,如果没有成功登录则统计全部 AND f_registro > COALESCE( (SELECT MAX(f_registro) FROM mo_bitacora WHERE usuario = 'user' AND d_accion = 'succesfull' AND f_registro BETWEEN (NOW() - INTERVAL 30 MINUTE) AND NOW()), '1970-01-01 00:00:00' );
代码逻辑解释
- 子查询获取最近成功登录时间:内部的
SELECT MAX(f_registro)会找出该用户在最近30分钟内的最后一次成功登录时间。如果用户在这段时间内没有成功登录过,子查询会返回NULL。 - COALESCE处理边界情况:
COALESCE函数会把NULL替换成一个极早的时间('1970-01-01'),这样所有30分钟内的失败记录都会被纳入统计,完美适配“从未成功登录过”的用户场景。 - 过滤旧失败记录:通过
f_registro > 最近成功登录时间的条件,直接排除掉成功登录之前的所有失败尝试,确保统计的是用户“重新尝试登录”后的失败次数。
为什么原来的SQL会出问题?
你原来的查询没有考虑“成功登录清零失败次数”的逻辑——只要是30分钟内的失败记录都会被统计,哪怕这些失败发生在用户一次成功登录之前。比如用户先失败3次→成功登录→又失败2次,你的原SQL会把3+2=5次都算进去,导致误封禁;而改进后的SQL只会统计成功登录后的2次失败,符合预期。
内容的提问来源于stack exchange,提问作者Jorge Saravia
相关产品推荐
相关产品推荐

