推荐一个验证码管理工具!
在 PHP 中对接谷歌验证码(Google Authenticator),通常指的是实现基于时间的一次性密码(TOTP)算法,用于两步验证(2FA)。
最主流且简单的方法是使用开源库phpgangsta/googleauthenticator。以下是完整的对接文档和步骤。
📦 1. 安装依赖
推荐使用 Composer 来管理依赖。在你的项目根目录下运行以下命令:
composerrequire phpgangsta/googleauthenticator🚀 2. 核心实现步骤
整个流程分为三个阶段:生成密钥与二维码->用户扫码绑定->验证登录。
第一步:生成密钥与二维码 (绑定阶段)
在用户的“安全设置”页面,你需要生成一个专属密钥和二维码,让用户用 Google Authenticator App 扫描。
<?phprequire_once__DIR__.'/vendor/autoload.php';usePHPGangsta_GoogleAuthenticator;// 1. 实例化类$ga=newPHPGangsta_GoogleAuthenticator();// 2. 生成一个随机的 Secret Key (密钥)// 注意:在实际应用中,你需要将这个 $secret 保存到数据库中,与当前用户绑定$secret=$ga->createSecret();echo"Secret is: ".$secret."\n\n";// 3. 生成二维码 URL// 参数说明:// - 'MyWebsite': 你的网站或应用名称 (Issuer)// - 'user@example.com': 用户的账号标识 (通常用邮箱或用户名)// - $secret: 上面生成的密钥$qrCodeUrl=$ga->getQRCodeGoogleUrl('MyWebsite',$secret,'user@example.com');echo"QR Code URL: ".$qrCodeUrl."\n\n";// 4. 在前端展示// 你可以在 HTML 中直接输出这个图片标签,让用户扫描echo"<img src='{$qrCodeUrl}' alt='Scan QR Code' />";// 5. (可选) 测试:获取当前时刻的验证码// 仅用于调试,不要在生产环境展示给用户$code=$ga->getCode($secret);echo"当前验证码 (仅供测试): ".$code."\n";?>第二步:用户绑定
- 用户打开手机上的Google AuthenticatorApp。
- 点击“+”号,选择“扫描二维码”。
- 扫描你页面上显示的二维码。
- App 中会出现你的网站名称和对应的 6 位动态验证码。
第三步:验证登录 (验证阶段)
当用户登录时,除了输入密码,还需要输入 App 上显示的 6 位验证码。
<?phprequire_once__DIR__.'/vendor/autoload.php';usePHPGangsta_GoogleAuthenticator;$ga=newPHPGangsta_GoogleAuthenticator();// 1. 从数据库中取出该用户的 Secret Key// 假设从数据库查出的密钥为 'VO2WA6NG3XZZEU4E'$dbSecret='VO2WA6NG3XZZEU4E';// 2. 获取用户提交的验证码 (来自表单 POST)$userCode=$_POST['code'];// 3. 验证验证码// 参数说明:// - $dbSecret: 用户的密钥// - $userCode: 用户提交的验证码// - 2: 容差 (Tolerance)。允许的时间偏差范围。// 谷歌验证码每 30 秒变一次。// 设置为 2 意味着允许前后各 2 个时间窗口 (即前后 1 分钟) 的误差,防止用户手机时间不准导致验证失败。$checkResult=$ga->verifyCode($dbSecret,$userCode,2);if($checkResult){echo'验证成功!';// 登录成功逻辑...}else{echo'验证失败,验证码错误。';// 登录失败逻辑...}?>🔑 关键方法说明
| 方法名 | 说明 | 参数 |
|---|---|---|
createSecret() | 生成随机密钥 | 无 |
getQRCodeGoogleUrl($name, $secret, $title) | 生成二维码链接 | $name: 网站名$secret: 密钥$title: 账号标识 |
verifyCode($secret, $code, $discrepancy) | 验证验证码是否正确 | $secret: 密钥$code: 验证码$discrepancy: 容差值 (默认 1) |
getCode($secret) | 获取当前时间的验证码 | $secret: 密钥 (通常用于调试) |
💡 安全建议
- 防止暴力破解:验证码只有 6 位数字,容易被爆破。务必在登录接口增加限制,例如:同一个 IP 或账号在 5 分钟内验证失败 5 次,则锁定账号或要求输入图形验证码。
- 防止重放攻击:虽然验证码有时间限制,但理论上同一个验证码在 30 秒内可以重复使用。高安全需求的场景下,可以记录用户最近一次成功使用的验证码,拒绝重复提交(需结合 Redis 等缓存实现)。
- 密钥存储:用户的 Secret Key 必须安全存储在数据库中,切勿泄露。如果密钥泄露,攻击者可以生成相同的验证码。
- 备份码:建议提供“备用码”功能。当用户手机丢失时,可以使用备用码登录并关闭两步验证。