简体   繁体   English

PHP - Google Authenticator URI 代码并不总是有效

[英]PHP - Google Authenticator URI codes don't always work

So i'm having a problem with google authenticator and my PHP.所以我在使用 google 身份验证器和我的 PHP 时遇到了问题。

So i'm using this library to generate QR codes: https://github.com/PHPGangsta/GoogleAuthenticator所以我使用这个库来生成二维码: https : //github.com/PHPGangsta/GoogleAuthenticator

So when I use my username to generate a code it works fine.因此,当我使用我的用户名生成代码时,它工作正常。 I get something along the lines of: otpauth://totp/username?secret=aCodeInBase32&issuer=Mysite我得到一些类似的东西:otpauth://totp/username?secret=aCodeInBase32&issuer=Mysite

For my case it is: otpauth://totp/NoahNok?secret=aCodeInBase32&issuer=Mysite就我而言,它是:otpauth://totp/NoahNok?secret=aCodeInBase32&issuer=Mysite

however when doing this for any other use I get an invalid token error on the Google Authenticator app.但是,当为任何其他用途执行此操作时,我在 Google 身份验证器应用程序上收到无效令牌错误。 It doesnt matter what else I put I always seem to get this error, yet it works fine for my account.不管我放了什么,我似乎总是遇到这个错误,但它对我的帐户来说很好用。

Eg this one doesn't work: otpauth://totp/Test?secret=KRSX&issuer=MySite例如,这个不起作用:otpauth://totp/Test?secret=KRSX&issuer=MySite

Is there something obvious im doing wrong?有什么明显的我做错了吗?

Code im using: Some queries before to get data我正在使用的代码:获取数据之前的一些查询

$g = new PHPGangsta_GoogleAuthenticator();
include("Base32.php");
$secret = substr(Base32::encode($username),0,-4);
echo $g->getQRCodeGoogleUrl($username, $secret, "MySite");

Generates QR URL生成二维码网址

    public function getQRCodeGoogleUrl($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.'';
}

Base32 is padded out to the nearest multiple of 8 characters, so it won't always have ==== at the end to strip off. Base32 被填充到最接近的 8 个字符的倍数,所以它不会总是在末尾有====来剥离。 From your examples we get:从你的例子中我们得到:

NoahNok => JZXWC2CON5VQ====

and:和:

Test => KRSXG5A=

So if you remove the last 4 characters always you'll create an invalid Base32 sequence for situations like the latter.因此,如果您始终删除最后 4 个字符,则会为后一种情况创建无效的 Base32 序列。 You could instead use rtrim like so:你可以像这样使用rtrim

$secret = rtrim(Base32::encode($username), '=')

to just remove all trailing equals (or just leave them in).只是删除所有尾随等于(或只是保留它们)。

Edit编辑

I was just thinking about this and while the above will fix the proximate issue, generating the secret this way is probably not a good idea.我只是在想这个,虽然上面的内容可以解决最接近的问题,但以这种方式生成秘密可能不是一个好主意。 If you think about it, setting the secret equal to the username means that if someone finds the username they can generate a valid OTP and therefore be able to pass their 2FA.如果您考虑一下,将机密设置为与用户名相同意味着如果有人找到用户名,他们可以生成有效的 OTP,因此能够通过他们的 2FA。

Secret should be unique and generally unguessable for this purpose, and the library you are using has a createSecret method to do this for you.为此,Secret 应该是唯一的并且通常是不可猜测的,您正在使用的库有一个createSecret方法可以为您执行此操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM