在现代 Web 开发中,安全性是一个至关重要的方面。Google 验证提供了双因素身份验证(2FA),极大地增强了用户账户的安全性。本文将介绍如何在 ThinkPHP 5 框架中集成 Google 验证和二维码生成功能,具体步骤如下:

 1. 安装必要的库

首先,需要安装 `endroid/qr-code` 和 `sonata-project/google-authenticator` 库。使用 Composer 安装这些库:


composer require endroid/qr-code
composer require sonata-project/google-authenticator


2. 创建 Google 验证控制器

在 ThinkPHP 5 的 `app\api\controller` 目录下创建一个名为 `GoogleAuth.php` 的控制器,代码如下:


<?php

namespace app\api\controller;

use app\common\controller\Api;
use Endroid\QrCode\Builder\Builder;
use Endroid\QrCode\Encoding\Encoding;
use Endroid\QrCode\Writer\PngWriter;
use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelHigh;
use Endroid\QrCode\Label\Alignment\LabelAlignmentCenter;
use Endroid\QrCode\Label\Font\NotoSans;
use Endroid\QrCode\RoundBlockSizeMode\RoundBlockSizeModeMargin;
use Sonata\GoogleAuthenticator\GoogleAuthenticator;
use app\common\model\User;

/**
 * 谷歌验证接口
 */
class GoogleAuth extends Api
{
    protected $noNeedLogin = [];
    protected $noNeedRight = '*';

    /**
     * 获取谷歌验证
     */
    public function index()
    {
        $modify = $this->request->post('modify');
        $userId = $this->auth->id;
        $userData = $this->getUserData($userId);
        $googleAuthenticator = new GoogleAuthenticator();
        if (empty($modify)) {
            $secret = empty($userData['secret']) ? $googleAuthenticator->generateSecret() : $userData['secret'];
        } else {
            $secret = $googleAuthenticator->generateSecret();
        }

        $issuer = 'yebinbing'; 
        $account = "126.com";
        $qrCodeData = $googleAuthenticator->getURL($issuer, $account, $secret);
        
        // 提取URL中的 data 参数值
        parse_str(parse_url($qrCodeData, PHP_URL_QUERY), $queryParams);
        $qrCodeData = urldecode($queryParams['data']);

        // 添加 logo 到二维码
        $logoPath = ROOT_PATH . 'public/assets/img/Rlogo.jpg';
        
        // 使用 Endroid\QrCode\Builder\Builder 来生成二维码
        $result = Builder::create()
            ->writer(new PngWriter())
            ->writerOptions([])
            // 二维码文本
            ->data($qrCodeData)
            // 内容编码
            ->encoding(new Encoding('UTF-8'))
            // 容错等级(越高二维码越密集)
            ->errorCorrectionLevel(new ErrorCorrectionLevelHigh())
            // 二维码内容区域大小
            ->size(300)
            // 二维码内容外边距大小
            ->margin(10)
            // 二维码内容圆形块尺寸模型
            ->roundBlockSizeMode(new RoundBlockSizeModeMargin())
            // 二维码中间区域logo图片
            ->logoPath($logoPath) // 添加 logo 路径
            ->logoResizeToWidth(80)
            ->logoResizeToHeight(80)
            // 二维码下方文字
            ->labelText('')
            ->labelFont(new NotoSans(20))
            ->labelAlignment(new LabelAlignmentCenter())
            // 验证读取器(默认情况下禁用)
            ->validateResult(false)
            // 执行生成器
            ->build();

        // 检查文件夹是否存在,不存在则创建
        $qrCodeDir = ROOT_PATH . 'public/qrtemp/';
        if (!is_dir($qrCodeDir)) {
            mkdir($qrCodeDir, 0755, true);
        }

        $qrCodePath = $qrCodeDir . "{$secret}.png";
        $result->saveToFile($qrCodePath);

        $data = ['secret' => $secret, 'qrcode' => request()->domain() . '/qrtemp/' . $secret . '.png', 'is_secret' => !empty($userData['secret'])];

// 获取当前验证码

//$data["code"] = $googleAuthenticator->getCode($secret);

$this->success("获取成功", $data); } /** * 谷歌验证 */ public function verify() { $userId = $this->auth->id; $secret = $this->request->post('secret'); $code = $this->request->post('code'); $userData = $this->getUserData($userId); if (!$userData) { $this->error(__('用户不存在')); } if (empty($secret)) { $this->error(__('Secret不正确')); } if (empty($code)) { $this->error(__('Code不正确')); } $googleAuthenticator = new GoogleAuthenticator(); $isValid = $googleAuthenticator->checkCode($secret, $code); if ($isValid) { // 保存到数据库 $this->saveUserData($userId, [ 'secret' => $secret, 'secrettime' => time() + (7 * 24 * 60 * 60), // 当前时间戳 + 7天的秒数 'session_id' => session_id(), // 获取当前会话的会话 ID ]); $this->success(__('验证成功')); } else { $this->error(__('验证失败')); } } private function getUserData($userId) { // 这里你需要实现获取用户数据的逻辑 $user = User::get($userId); return $user ? $user->toArray() : null; } private function saveUserData($userId, $data) { // 这里你需要实现保存用户数据的逻辑 $user = User::get($userId); if ($user) { $user->save($data); } } }


3. 代码说明

获取谷歌验证 (`index` 方法)

在 `index` 方法中,我们首先检查是否需要修改(生成新的密钥)。然后,我们使用 `GoogleAuthenticator` 生成或获取密钥,并生成对应的二维码 URL。通过 `Endroid\QrCode\Builder\Builder` 来生成包含 LOGO 的二维码,并将其保存到本地。

谷歌验证 (`verify` 方法)

在 `verify` 方法中,我们接收用户输入的密钥和验证码,并使用 `GoogleAuthenticator` 验证该验证码是否有效。如果验证通过,将相关信息保存到数据库中。

通过集成 Google 验证和二维码生成功能,您可以大大增强 Web 应用的安全性和用户体验。

使用这些方法,你可以在 ThinkPHP 5 中轻松实现 Google 验证功能,为用户提供安全可靠的双因素认证机制。

点赞(0)

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部