Laravel默认不内置暴力破解防护,因Auth::attempt()仅校验凭证、无失败计数、不限流、不锁账号,且错误响应明确、无验证码、无请求频率限制。

Laravel 默认不内置暴力破解防护,Hash::check() 和登录逻辑本身不记录失败次数、不限流、不锁账号——这意味着开箱即用的 Laravel 应用在 Low 级别 DVWA 那种场景下,和裸奔没区别。
为什么 Laravel 登录接口容易被暴力破解
核心问题不在密码哈希,而在认证流程缺失防护层。Laravel 的 Auth::attempt() 只做凭证校验,成功返回 true,失败也只返回 false,中间没有任何计数、冷却或响应扰动机制。
- 失败响应状态码始终是 200(除非你手动改),攻击者可稳定解析 HTML 或 JSON 判断是否命中
- 无请求频率限制:同一 IP、同一账号、甚至同一会话,可无限重试
- 无验证码介入点:默认登录表单不触发 CAPTCHA,
VerifyCsrfToken中间件对暴力请求无效 - 错误提示过于明确:比如返回
"Invalid credentials",等于告诉攻击者“用户名存在但密码错”,方便针对性爆破
Laravel 实现基础防爆破的 3 种可行方式
不用第三方包也能快速补上缺口,关键是把“失败行为”变成可观察、可干预、可阻断的信号。
- 用
RateLimiter::attempt()限制 IP 级请求频次:在登录控制器中加一行if (! RateLimiter::attempt('login:'.$request->ip(), $perMinute = 10)) { ... },10 次/分钟是常见起点 - 对账号维度做失败计数:在数据库加
failed_login_attempts字段 +locked_until时间戳,每次失败递增并检查是否超阈值(如 5 次),超则写入锁定时间 - 混淆失败响应:不要直接返回
"Invalid credentials",统一返回"Authentication failed";成功时再跳转,避免响应体长度或关键字成为判断依据
使用 laravel-2fa 或 laravel-throttle-request 的实际取舍
第三方包能省代码,但得看清它插在哪一层、是否覆盖你的认证路径。
-
laravel-throttle-request是全局中间件,基于 IP+URI 限流,适合保护整个/login路由,但无法区分“用户 A 连错 10 次”和“IP X 扫了 10 个不同用户” -
laravel-2fa本质是增加第二因子,不解决暴力破解本身,只让撞库失效;如果攻击者已拿到有效账号+密码,2FA 反而可能因短信/邮件延迟被绕过(如用已泄露的备用邮箱重置) - 真正匹配 DVWA-Low 场景的方案,其实是组合:用
RateLimiter控制速率 + 自定义登录失败事件监听器写入日志 + Nginx 层对异常 UA 或高频 429 做 IP 封禁
最易被忽略的细节:APP_KEY 泄露会让所有防护形同虚设
如果你用了 Crypt::encrypt() 加密 session 或 token 存在数据库里,又把 APP_KEY 提交到了 Git 或日志中,攻击者拿到密钥后,不仅能解出 session 内容伪造登录,还能反向生成合法的 CSRF token 或 remember_token,直接绕过所有基于令牌的防护逻辑。
哪怕你给登录加了 10 层限流,只要 APP_KEY 在攻击者手里,他就能伪造任意合法请求——这才是比暴力破解更隐蔽、更致命的入口。


















