php - 如何在 PHP 中使用 Google Authenticator 生成唯一的二维码?

标签 php mysql qr-code google-authenticator

希望我们的 PHP 系统上的每个用户都有一个唯一的二维码。我已经实现了 Google 身份验证器系统,但它只能为每个用户生成相同的二维码,并且一个用户可以使用他们的代码登录另一个用户的帐户。

如何让 Google 身份验证器为每个用户生成唯一的代码?我需要将什么值/变量传递给 Google 身份验证器,以便它为我们系统上的每个用户帐户提供唯一的代码?

我们尝试传递用户的电子邮件地址或用户名,但尽管电子邮件地址是唯一的,但身份验证器会发回相同的二维码。

[1]使用 username ,用户名变量名为 $name

public function getQR($name, $secret, $title = null, $params = array())
    {
        $width = !empty($params['width']) && (int) $params['width'] > 0 ? (int) $params['width'] : 200;
        $height = !empty($params['height']) && (int) $params['height'] > 0 ? (int) $params['height'] : 200;
        $level = !empty($params['level']) && array_search($params['level'], array('L', 'M', 'Q', 'H')) !== false ? $params['level'] : 'M';


        $urlencoded = urlencode('otpauth://totp/'.$name.'?secret='.$secret.'');
        if (isset($title)) {
            $urlencoded .= urlencode('&issuer='.urlencode($title));
        }

        return 'https://chart.googleapis.com/chart?chs='.$width.'x'.$height.'&chld='.$level.'|0&cht=qr&chl='.$urlencoded.'';
    }

    public function verifyCode($secret, $code, $discrepancy = 1, $currentTimeSlice = null)
    {
        if ($currentTimeSlice === null) {
            $currentTimeSlice = floor(time() / 30);
        }

        if (strlen($code) != 6) {
            return false;
        }

        for ($i = -$discrepancy; $i <= $discrepancy; ++$i) {
            $calculatedCode = $this->getCode($secret, $currentTimeSlice + $i);
            if ($this->timingSafeEquals($calculatedCode, $code)) {
                return true;
            }
        }

        return false;
    }
<小时/>

[2]使用 email ,email 变量名为 $email

public function getQR($email, $secret, $title = null, $params = array())
    {
        $width = !empty($params['width']) && (int) $params['width'] > 0 ? (int) $params['width'] : 200;
        $height = !empty($params['height']) && (int) $params['height'] > 0 ? (int) $params['height'] : 200;
        $level = !empty($params['level']) && array_search($params['level'], array('L', 'M', 'Q', 'H')) !== false ? $params['level'] : 'M';


        $urlencoded = urlencode('otpauth://totp/'.$email.'?secret='.$secret.'');
        if (isset($title)) {
            $urlencoded .= urlencode('&issuer='.urlencode($title));
        }

        return 'https://chart.googleapis.com/chart?chs='.$width.'x'.$height.'&chld='.$level.'|0&cht=qr&chl='.$urlencoded.'';
    }

    public function verifyCode($secret, $code, $discrepancy = 1, $currentTimeSlice = null)
    {
        if ($currentTimeSlice === null) {
            $currentTimeSlice = floor(time() / 30);
        }

        if (strlen($code) != 6) {
            return false;
        }

        for ($i = -$discrepancy; $i <= $discrepancy; ++$i) {
            $calculatedCode = $this->getCode($secret, $currentTimeSlice + $i);
            if ($this->timingSafeEquals($calculatedCode, $code)) {
                return true;
            }
        }

        return false;
    }

我希望该代码为每个用户生成唯一的二维码,以便每个用户在其手机上的 Google 身份验证器应用中拥有自己的身份验证码。

最佳答案

这个 secret 只不过是一个随机的 Base32 字符串。 所以可以像

一样简单地完成
 substr( str_shuffle( "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" ), 0, 32 );

其中“ABCDEFGHIJKLMNOPQRSTUVWXYZ234567”是base32字母表

关于php - 如何在 PHP 中使用 Google Authenticator 生成唯一的二维码?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56321547/

相关文章:

php - 当调用 PHP 函数并返回某些内容时,它会停止运行下面的代码吗?

php - mySQL 给出不正确的结果

php - 根据第一个选择选项更改表单选择选项?

php - 使用php生成二维码

ruby-on-rails - Rails API 创建二维码并将图像存储在 active_storage 中

grails - 无法添加 qrcode grails 插件?

php - Angular/Laravel - 从 mysql 数据库输出 json 数据

php - 如何将 POST Json 和图像发送到 php alamofire

MySQL:在行列表中使用给定值找到合适的行

php - 使用 select 语句和 php 变量插入 MySQL