验证码过期必须用cache::put()显式设ttl,禁用session和前端倒计时;因session驱动不统一、无法联动限流、forget易失效,而redis中cache::put带秒级ttl原子可靠。

验证码过期时间必须用 Cache::put() 显式设置 TTL,不能依赖 session 或前端倒计时 —— Laravel 的缓存驱动(尤其是 Redis)才真正控制实际失效行为。
为什么不能用 session 存验证码
session 驱动不统一:database、file、redis 下的过期清理逻辑不一致;无法与登录失败次数联动限流;用户关浏览器或网络中断会导致 session()->forget() 不执行,key 残留。而 Cache::put('captcha_'.$ip, $code, 120) 在 Redis 中是原子性设置带秒级 TTL 的 key,可靠且可预测。
生成时怎么设过期时间(推荐写法)
直接传秒数或 Carbon 实例,别用模糊描述:
-
Cache::put('captcha_'.md5($request->ip().$request->userAgent()), $code, 120)—— 2 分钟,IP+UA 组合防枚举 -
Cache::put('captcha_'.$request->ip(), $code, now()->addMinutes(3))—— 3 分钟,语义清晰 - 避免写
Cache::put(..., 60*2)这类魔法数字,可读性差且易出错
验证时怎么判断是否已过期
别直接 Cache::get($key) === $input —— Redis 是惰性删除,key 可能已过期但还没被清理,get() 返回 null,导致空值比对失败或报错。正确顺序是:
- 先
Cache::has($key)确认 key 存在且未过期 - 再
Cache::get($key) === $input - 完整逻辑:
if (!Cache::has($key) || Cache::get($key) !== $input) - 验证通过后立刻
Cache::forget($key),防止重放
容易忽略的关键点
服务器时区没设 UTC 会导致 now()->addMinutes(2) 计算偏移;Redis 时间与 PHP 时间不同步会引发「明明没超时却提示错误」;key 命名没绑定 IP 或 UA,攻击者可固定 key 暴力刷码。这些细节不处理,哪怕 TTL 设对了,线上仍会出问题。











