Laravel如何实现登录时集成图形或短信验证码?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1068个文字,预计阅读时间需要5分钟。
图形验证码适用于绝大多数Web登录页,响应快、无第三方依赖、用户刷新成本低;短信验证码仅以手机号为唯一标识且需强身份核验时才值得引入——例如银行类操作或新设备首次登录。混用两者反而增加维护负担,如session与SMS provider的状态不一致是常见故障源。
常见错误现象:用户填对图形码却提示“验证码错误”,大概率是 session 未正确启动或跨域导致 session_id 丢失;短信发送成功但校验总失败,多因缓存键名拼写不一致(如用 phone:138xxxx 存,却用 sms:138xxxx 取)。
- 图形验证码优先走 Laravel 自带的
captcha扩展(如mews/captcha),它默认绑定session,无需额外配置存储 - 短信验证码必须自己控制生命周期,推荐用
Cache::put('sms:'.$phone, $code, 300)显式设 5 分钟过期 - 别把图形码和短信码存在同一个字段校验逻辑里——
validateCaptcha()和validateSmsCode()应该是两个独立方法
Laravel 图形验证码怎么接进登录表单
关键是让验证码校验和 Laravel 的 FormRequest 或 Validator 无缝协作,而不是单独写个中间件去拦截。
使用场景:登录页 POST /login 提交时同步校验图形码是否匹配。
- 安装
mews/captcha后,在 Blade 中用{!! captcha_img() !!}渲染图片,再加一个<input name="captcha"> - 在登录用的
FormRequest的rules()方法里加上'captcha' => 'required|captcha'—— 这个captcha规则由扩展自动注册 - 注意:图形码默认走
session,所以控制器里不能提前调用session()->regenerate(),否则旧码失效 - 开发环境调试时,可临时在
config/captcha.php里把'expire' => 60改大些,避免反复刷新失败
短信验证码的请求频率和并发怎么防
不是加个 throttle 中间件就完事——短信接口本身有频控,后端还得兜底防止撞库或暴力刷号。
参数差异:throttle:5,1 是针对 IP 限流,对换号攻击无效;真正要控的是「同一手机号单位时间内的请求次数」。
- 发码前先查缓存:
if (Cache::has('sms_sent:'.$phone)) { return response(['msg' => '请稍后再试'], 429); } - 发码成功后立刻写两份缓存:
Cache::put('sms:'.$phone, $code, 300)用于校验,Cache::put('sms_sent:'.$phone, true, 60)用于限流(1 分钟内不能再发) - 别用数据库存待验证的短信码——高并发下
INSERT ... ON DUPLICATE KEY UPDATE容易锁表,缓存更轻量也更准 - 前端按钮倒计时必须和服务端限流逻辑对齐,否则用户会误以为「点不动是前端 bug」
验证码校验失败后为什么总是清不掉旧 session
因为 Laravel 的 captcha 扩展在验证失败时不会主动清除已生成的验证码 session 值,下次刷新页面仍用旧值比对,导致「明明换了图,还说错」。
性能影响:残留的 captcha session 数据虽小,但在高频登录页上会累积成无效 session 垃圾。
- 手动清除方式:在登录控制器的
failedLoginResponse()或自定义异常处理里加session()->forget('captcha') - 更稳妥的做法是重写
CaptchaServiceProvider的验证逻辑,在fails()方法末尾触发清除 - 如果用了 Redis 存 session,可通过
redis-cli keys "*captcha*"快速确认是否有堆积 - 这个点特别容易被忽略——测试时人工点几次看不出问题,压测或上线后才暴露
本文共计1068个文字,预计阅读时间需要5分钟。
图形验证码适用于绝大多数Web登录页,响应快、无第三方依赖、用户刷新成本低;短信验证码仅以手机号为唯一标识且需强身份核验时才值得引入——例如银行类操作或新设备首次登录。混用两者反而增加维护负担,如session与SMS provider的状态不一致是常见故障源。
常见错误现象:用户填对图形码却提示“验证码错误”,大概率是 session 未正确启动或跨域导致 session_id 丢失;短信发送成功但校验总失败,多因缓存键名拼写不一致(如用 phone:138xxxx 存,却用 sms:138xxxx 取)。
- 图形验证码优先走 Laravel 自带的
captcha扩展(如mews/captcha),它默认绑定session,无需额外配置存储 - 短信验证码必须自己控制生命周期,推荐用
Cache::put('sms:'.$phone, $code, 300)显式设 5 分钟过期 - 别把图形码和短信码存在同一个字段校验逻辑里——
validateCaptcha()和validateSmsCode()应该是两个独立方法
Laravel 图形验证码怎么接进登录表单
关键是让验证码校验和 Laravel 的 FormRequest 或 Validator 无缝协作,而不是单独写个中间件去拦截。
使用场景:登录页 POST /login 提交时同步校验图形码是否匹配。
- 安装
mews/captcha后,在 Blade 中用{!! captcha_img() !!}渲染图片,再加一个<input name="captcha"> - 在登录用的
FormRequest的rules()方法里加上'captcha' => 'required|captcha'—— 这个captcha规则由扩展自动注册 - 注意:图形码默认走
session,所以控制器里不能提前调用session()->regenerate(),否则旧码失效 - 开发环境调试时,可临时在
config/captcha.php里把'expire' => 60改大些,避免反复刷新失败
短信验证码的请求频率和并发怎么防
不是加个 throttle 中间件就完事——短信接口本身有频控,后端还得兜底防止撞库或暴力刷号。
参数差异:throttle:5,1 是针对 IP 限流,对换号攻击无效;真正要控的是「同一手机号单位时间内的请求次数」。
- 发码前先查缓存:
if (Cache::has('sms_sent:'.$phone)) { return response(['msg' => '请稍后再试'], 429); } - 发码成功后立刻写两份缓存:
Cache::put('sms:'.$phone, $code, 300)用于校验,Cache::put('sms_sent:'.$phone, true, 60)用于限流(1 分钟内不能再发) - 别用数据库存待验证的短信码——高并发下
INSERT ... ON DUPLICATE KEY UPDATE容易锁表,缓存更轻量也更准 - 前端按钮倒计时必须和服务端限流逻辑对齐,否则用户会误以为「点不动是前端 bug」
验证码校验失败后为什么总是清不掉旧 session
因为 Laravel 的 captcha 扩展在验证失败时不会主动清除已生成的验证码 session 值,下次刷新页面仍用旧值比对,导致「明明换了图,还说错」。
性能影响:残留的 captcha session 数据虽小,但在高频登录页上会累积成无效 session 垃圾。
- 手动清除方式:在登录控制器的
failedLoginResponse()或自定义异常处理里加session()->forget('captcha') - 更稳妥的做法是重写
CaptchaServiceProvider的验证逻辑,在fails()方法末尾触发清除 - 如果用了 Redis 存 session,可通过
redis-cli keys "*captcha*"快速确认是否有堆积 - 这个点特别容易被忽略——测试时人工点几次看不出问题,压测或上线后才暴露

