跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

Laravel TwoFactor认证_Google两步验证实现【方法】

Laravel ≥9.25 原生支持 Google Authenticator,需三字段(two_factor_secret、two_factor_recovery_codes、two_factor_confirmed_at)齐全且正确配置,verifyKey() 必须传 $window=1,恢复码为加密 JSON 格式,two_factor_confirmed_at 为空则校验被拦截。 直接用 Laravel 原生的
TwoFactorAuthenticatable
trait 就能跑通 Google Authenticator,不需要额外装第三方包——前提是你的 Laravel 版本 ≥ 9.25(对应
laravel/framework
v9.25.0+),且已启用 Sanctum 或 Session Guard。 确认 Laravel 版本是否支持原生两步验证 Laravel 在 9.25 版本中正式将
TwoFactorAuthenticatable
trait 和配套数据库字段、验证逻辑合并进核心,此前版本(如 8.x 或 9.0–9.24)调用
$user->enableTwoFactorAuthentication()
会报错
Method enableTwoFactorAuthentication does not exist
。 运行
composer show laravel/framework
查看实际版本号 若低于 9.25,必须升级框架,或退而使用
pragmarx/google2fa-laravel
包(注意它不兼容 Laravel 10 的 PHP 8.2+ 强类型约束,需锁定
v6.0.0
) 原生实现依赖
Illuminate\Auth\Passwords\PasswordBrokerManager
和
Illuminate\Support\InteractsWithTime
,低版本手动复制 trait 无法补全底层校验逻辑 数据库迁移必须包含 three 个字段 只加
two_factor_secret
是不够的,
useRecoveryCode()
和状态判断会直接失败。Laravel 原生验证流程严格检查以下三字段是否存在且可写:
two_factor_secret
:TEXT 类型,存储 Base32 编码后的密钥(如
JBSWY3DPEHPK3PXP
),不能为 NULL
two_factor_recovery_codes
:TEXT 类型,存 JSON 编码的加密数组(如
"{\"0\":\"xk9m2v8q\",\"1\":\"t7r4f1p6\"}"
),不是明文逗号分隔
two_factor_confirmed_at
:TIMESTAMP NULLABLE,用于区分“已启用但未确认”和“已启用且已确认”两种状态 漏掉任意一个,调用
$user->confirmTwoFactorAuthentication()
会静默失败,前端始终卡在“扫描二维码后点击确认”步骤。
verifyKey()
失败的常见真实原因 用户输入 6 位验证码却提示
Invalid verification code
,大概率不是算法问题,而是上下文断开或参数错配: 没传
$window = 1
参数:原生
verifyKey()
默认
$window = 0
,即只校验当前时间窗口(±0 秒),服务器与手机时钟偏差 >30 秒就必然失败;生产环境务必显式传
1
或
2
Session 未启动或已过期:TOTP 校验前需先通过密码登录并保持有效 session,否则
Auth::user()
为空,
verifyKey()
内部直接返回 false 密钥被二次 base64_decode:
two_factor_secret
字段内容是 Base32 编码字符串,不是 Base64;如果中间层(如 API 网关或日志脱敏)误做 Base64 解码再存库,会导致密钥损坏 恢复码校验失败别急着重输 报
Invalid recovery code
时,先查
two_factor_recovery_codes
字段值是否为空或 JSON 格式错误(比如被手动编辑成明文字符串),再确认是否已用过该码: 原生逻辑每次成功调用
useRecoveryCode()
后,会从 JSON 数组中 移除该码 并重写整个字段;如果数据库字段被其他进程并发修改,可能造成数组丢失 不要用
Google2FA::generateBackupCodes()
替换原生生成的恢复码——前者返回明文数组,后者存的是加密 JSON,混用会导致
json_decode()
报错后整个校验流程中断 用户重新启用 2FA 时,旧恢复码自动失效,但前端可能还缓存着旧页面;需强制跳转到新设置页并清空本地 storage 最隐蔽的问题是:
two_factor_confirmed_at
为 NULL 时,即使恢复码正确,
canUseTwoFactor()
也会返回 false,导致中间件直接拦截请求不进校验逻辑。

相关文章