希望我们的PHP系统上的每个用户都拥有唯一的QR码。我已经实现了Google Authenticator系统,但是它只能为每个用户生成相同的QR码,并且一个用户可以使用他们的代码登录到另一个用户的帐户。
如何让Google Authenticator为每个用户生成唯一的代码?我需要传递什么值/变量给Google Authenticator才能为我们系统上的每个用户帐户提供唯一的代码?
我们尝试传递用户的电子邮件地址或用户名,但是尽管电子邮件地址是唯一的,但身份验证器仍会发送相同的QR码。
[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
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;
}
我希望该代码为每个用户生成一个唯一的QR码,以便每个用户在手机上的Google身份验证器应用中都有自己的身份验证代码。
答案 0 :(得分:0)
秘密无非就是一个随机的base32字符串。 因此可以像
一样简单MyCompletableFuture.supplyAsync(() -> "test")
.thenApplyAsync(String::toUpperCase)
.thenAcceptAsync(System.out::println);
其中“ ABCDEFGHIJKLMNOPQRSTUVWXYZ234567”是base32字母
答案 1 :(得分:0)
您的代码看起来与 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;
}