def login(username, password):
if username in login_attempts and login_attempts[username]['attempts'] >= 5:
if time.time() - login_attempts[username]['last_attempt'] < 60:
raise Exception("账户暂时锁定,请稍后再试")
else:
login_attempts[username] = {'attempts': 0}
# 验证逻辑
if not validate_credentials(username, password):
if username not in login_attempts:
login_attempts[username] = {'attempts': 0}
login_attempts[username]['attempts'] += 1
login_attempts[username]['last_attempt'] = time.time()
raise Exception("用户名或密码错误")
首先,限制登录次数是个好思路,但别在前端做延迟验证,这相当于把门锁挂在墙上给别人看。你应该在服务端实现登录失败的计数器,比如连续失败5次后锁定账户或增加指数级延迟。代码可以这样写:
其次,加一个验证码机制也很重要。对于频繁失败的IP地址或者账户,要求输入验证码才能继续尝试。这能有效防止自动化工具扫库。
再来说说密码存储的问题。如果你还在用简单的哈希算法存密码,那即使用户设了强密码也没用。推荐用专门设计的慢哈希算法,比如
bcrypt或argon2,它们通过增加计算成本让暴力破解变得极其耗时。最后,启用多因素认证(MFA)。这是最有效的手段之一,就算密码被猜出来了,攻击者没拿到二次验证的动态码也进不去。
总结一下,防御字典攻击不能只靠密码复杂度,而要组合使用服务端限流、验证码、强哈希算法和多因素认证。这些方法一起上,基本就能挡住大部分攻击了。
先说指数级延迟,不是简单用前端setTimeout,而是服务端实现:第一次失败等1秒,第二次2秒,第三次4秒...这样下去,就算对方用自动化工具,也会因为时间成本太高而放弃。
再来说验证码,连续输错几次密码后就弹出来,这个得放在后端校验,别信前端的勾选。可以用
Google reCAPTCHA这种成熟的方案,官方文档里推荐过。另外,记得给密码加盐哈希存储,用
bcrypt或者Argon2算法。即使数据库泄露了,攻击者也没法直接用字典破解。最后提醒一下,这些措施最好组合使用,单靠哪一项都不够牢靠。写代码的时候注意性能影响,尤其是验证码和哈希计算这部分。