[英]How to generate unique QR codes with Google Authenticator in PHP?
希望我們 PHP 系統上的每個用戶都有一個唯一的二維碼。 我已經實現了 Google Authenticator 系統,但它只為每個用戶生成相同的二維碼,一個用戶可以使用他們的代碼登錄另一個用戶的帳戶。
如何讓 Google Authenticator 為每個用戶生成唯一代碼? 我需要將什么值/變量傳遞給 Google 身份驗證器才能為我們系統上的每個用戶帳戶提供唯一代碼?
我們嘗試傳遞用戶的電子郵件地址或用戶名,但盡管電子郵件地址是唯一的,但身份驗證器還是發回了相同的二維碼。
[1]使用 username , 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 身份驗證器應用程序中都有自己的身份驗證代碼。
秘密只不過是一個隨機的 base32 字符串。 所以可以像這樣簡單地完成
substr( str_shuffle( "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" ), 0, 32 );
其中“ABCDEFGHIJKLMNOPQRSTUVWXYZ234567”是base32字母表
您的代碼看起來與https://github.com/PHPGangsta/GoogleAuthenticator非常相似,導致不同用戶使用類似 QR 碼的問題是您為他們使用相同的秘密。
每個用戶都必須擁有獨一無二的秘密!
PHPGangsta 有一個生成偽隨機秘密的函數:
public function createSecret($secretLength = 16)
{
$validChars = $this->_getBase32LookupTable();
// Valid secret lengths are 80 to 640 bits
if ($secretLength < 16 || $secretLength > 128) {
throw new Exception('Bad secret length');
}
$secret = '';
$rnd = false;
if (function_exists('random_bytes')) {
$rnd = random_bytes($secretLength);
} elseif (function_exists('mcrypt_create_iv')) {
$rnd = mcrypt_create_iv($secretLength, MCRYPT_DEV_URANDOM);
} elseif (function_exists('openssl_random_pseudo_bytes')) {
$rnd = openssl_random_pseudo_bytes($secretLength, $cryptoStrong);
if (!$cryptoStrong) {
$rnd = false;
}
}
if ($rnd !== false) {
for ($i = 0; $i < $secretLength; ++$i) {
$secret .= $validChars[ord($rnd[$i]) & 31];
}
} else {
throw new Exception('No source of secure random');
}
return $secret;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.