来自:https://blog.lmlyz.online/index/detail/id/55.html
1、下载PHP版的GoogleAuthenticator,代码如下,可新建文件googleAuthenticator.php然后复制粘贴进去

class PHPGangsta_GoogleAuthenticator
{
protected $_codeLength = 6;

/*** Create new secret.* 16 characters, randomly chosen from the allowed base32 characters.** @param int $secretLength** @return string*/
public function createSecret($secretLength = 16)
{$validChars = $this->_getBase32LookupTable();// Valid secret lengths are 80 to 640 bitsif ($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;
}/*** Calculate the code, with given secret and point in time.** @param string   $secret* @param int|null $timeSlice** @return string*/
public function getCode($secret, $timeSlice = null)
{if ($timeSlice === null) {$timeSlice = floor(time() / 30);}$secretkey = $this->_base32Decode($secret);// Pack time into binary string$time = chr(0).chr(0).chr(0).chr(0).pack('N*', $timeSlice);// Hash it with users secret key$hm = hash_hmac('SHA1', $time, $secretkey, true);// Use last nipple of result as index/offset$offset = ord(substr($hm, -1)) & 0x0F;// grab 4 bytes of the result$hashpart = substr($hm, $offset, 4);// Unpak binary value$value = unpack('N', $hashpart);$value = $value[1];// Only 32 bits$value = $value & 0x7FFFFFFF;$modulo = pow(10, $this->_codeLength);return str_pad($value % $modulo, $this->_codeLength, '0', STR_PAD_LEFT);
}/*** Get QR-Code URL for image, from google charts.** @param string $name* @param string $secret* @param string $title* @param array  $params** @return string*/
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.'';
}/*** Check if the code is correct. This will accept codes starting from $discrepancy*30sec ago to $discrepancy*30sec from now.** @param string   $secret* @param string   $code* @param int      $discrepancy      This is the allowed time drift in 30 second units (8 means 4 minutes before or after)* @param int|null $currentTimeSlice time slice if we want use other that time()** @return bool*/
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;
}/*** Set the code length, should be >=6.** @param int $length** @return PHPGangsta_GoogleAuthenticator*/
public function setCodeLength($length)
{$this->_codeLength = $length;return $this;
}/*** Helper class to decode base32.** @param $secret** @return bool|string*/
protected function _base32Decode($secret)
{if (empty($secret)) {return '';}$base32chars = $this->_getBase32LookupTable();$base32charsFlipped = array_flip($base32chars);$paddingCharCount = substr_count($secret, $base32chars[32]);$allowedValues = array(6, 4, 3, 1, 0);if (!in_array($paddingCharCount, $allowedValues)) {return false;}for ($i = 0; $i < 4; ++$i) {if ($paddingCharCount == $allowedValues[$i] &&substr($secret, -($allowedValues[$i])) != str_repeat($base32chars[32], $allowedValues[$i])) {return false;}}$secret = str_replace('=', '', $secret);$secret = str_split($secret);$binaryString = '';for ($i = 0; $i < count($secret); $i = $i + 8) {$x = '';if (!in_array($secret[$i], $base32chars)) {return false;}for ($j = 0; $j < 8; ++$j) {$x .= str_pad(base_convert(@$base32charsFlipped[@$secret[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT);}$eightBits = str_split($x, 8);for ($z = 0; $z < count($eightBits); ++$z) {$binaryString .= (($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48) ? $y : '';}}return $binaryString;
}/*** Get array with all 32 characters for decoding from/encoding to base32.** @return array*/
protected function _getBase32LookupTable()
{return array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', //  7'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31'=',  // padding char);
}/*** A timing safe equals comparison* more info here: http://blog.ircmaxell.com/2014/11/its-all-about-time.html.** @param string $safeString The internal (safe) value to be checked* @param string $userString The user submitted (unsafe) value** @return bool True if the two strings are identical*/
private function timingSafeEquals($safeString, $userString)
{if (function_exists('hash_equals')) {return hash_equals($safeString, $userString);}$safeLen = strlen($safeString);$userLen = strlen($userString);if ($userLen != $safeLen) {return false;}$result = 0;for ($i = 0; $i < $userLen; ++$i) {$result |= (ord($safeString[$i]) ^ ord($userString[$i]));}// They are only identical strings if $result is exactly 0...return $result === 0;
}

}

2、新建文件googlelp.php,这里简要写一下使用方法

require_once ‘googleAuthenticator.php’;
$ga = new PHPGangsta_GoogleAuthenticator();
//创建一个新的"安全密匙SecretKey"
//把本次的"安全密匙SecretKey" 入库,和账户关系绑定,客户端也是绑定这同一个"安全密匙SecretKey"
$secret = ga−&gt;createSecret();echo&quot;安全密匙SecretKey:&quot;.ga-&gt;createSecret(); echo &quot;安全密匙SecretKey: &quot;.ga−>createSecret();echo"安全密匙SecretKey:".secret."\n\n";
$oneCode = ga−&gt;getCode(ga-&gt;getCode(ga−>getCode(secret); //服务端计算"一次性验证码"
echo ’
';
echo “服务端计算的验证码是:”.$oneCode."\n\n";
//把提交的验证码和服务端上生成的验证码做对比
// $secret 服务端的 “安全密匙SecretKey”
// $oneCode 手机上看到的 “一次性验证码”
// 最后一个参数 为容差时间,这里是2 那么就是 2* 30 sec 一分钟.
// 这里改成自己的业务逻辑
$checkResult = ga−&gt;verifyCode(ga-&gt;verifyCode(ga−>verifyCode(secret, oneCode,1);if(oneCode, 1); if (oneCode,1);if(checkResult) {
echo ‘匹配! OK’;
} else {
echo ‘不匹配! FAILED’;
}
secret为用户安全密钥,每一个用户都不一样,这里可以将它存入到用户表中。secret为用户安全密钥,每一个用户都不一样,这里可以将它存入到用户表中。secret为用户安全密钥,每一个用户都不一样,这里可以将它存入到用户表中。oneCode是用户端生成的一次性验证码,也就是下面需要下载的软件中自动生成的验证码,这里只是为了对比,所以直接输出来。

3、下载身份验证器:

Android移动设备

在您手机的应用市场搜索“Google身份验证器”或“Google Authenticator”,下载安装即可。拥有Google身份验证器的市场有:Google Play;应用汇;安卓市场;百度移动应用;优亿市场;安智市场 等

iOS移动设备

应用市场,搜索“Google Authenticator”,下载安装即可。

4、在身份验证器中输入安全密钥绑定账号,身份验证器每隔一段时间将会变换一次验证码,此验证码和服务端生成的验证码一致,因此可将他们进行匹配来确定是否是用户本人

PHP使用谷歌令牌做登录验证相关推荐

  1. ASP.NET MVC 实现统一登录验证

    1.先写个主页面 using System; using System.Collections.Generic; using System.Linq; using System.Web; using ...

  2. .net Core Jwt登录验证刷新Token

    使用 jwt做登录验证的时候,token的过期时间的固定的, 也就是只要经过了一定的时间肯定会过期.有可能用户用着系统就突然提示登录失效了.这里通过在行为结果过滤器Result Filter中刷新To ...

  3. 三方支付四方支付聚合支付系统 集成 支付宝分账 代付 多商户 短信邮件 谷歌令牌验证

    三方 四方支付聚合系统 集成 支付宝分账 短信 邮件 谷歌令牌多种验证 1.系统为成熟运营版,完美对接邮件系统2.短信系统为阿里和短信宝,可多通道切换 3.增加安全机制集成了谷歌令牌 4.成熟的商户, ...

  4. 用双因子认证2FA替换Google authenticator谷歌令牌,助力准上市公司实现等保安全审计

    21世纪初,某人力资源科技公司试水HR SaaS赛道,以大客户为目标客群,持续深耕,稳扎稳打,如今已是一家专门为中大型企业提供一体化HR SaaS及人才管理产品/解决方案的头部企业.其产品覆盖了从员工 ...

  5. weblogic登录验证被拒绝_使用Kubernetes身份在微服务之间进行身份验证

    如果您的基础架构由相互交互的多个应用程序组成,则您可能会遇到保护服务之间的通信安全以防止未经身份验证的请求的问题. 想象一下,有两个应用程序: API datastore 您可能希望数datastor ...

  6. 微信加密与登录验证分析

    微信加密与安全通信流程分析 背景 ​ 微信渐渐已经成为了大多数中国人日常会话的通讯工具.微信的通信安全,很大程度上保证了普通民众的数据安全,也因此显得十分重要. ​ 本文主要在其他对微信研究的基础上, ...

  7. Spring Security技术栈学习笔记(十三)Spring Social集成第三方登录验证开发流程介绍

    开发第三方登录,我们必须首先要了解OAuth协议(本文所讲述的OAuth协议指的是OAuth2协议),本文首先简单介绍OAuth协议,然后基于Spring Social来阐述开发第三方登录需要做哪些准 ...

  8. Spring Security技术栈学习笔记(十四)使用Spring Social集成QQ登录验证方式

    上一篇文章<Spring Security技术栈开发企业级认证与授权(十三)Spring Social集成第三方登录验证开发流程介绍>主要是介绍了OAuth2协议的基本内容以及Spring ...

  9. shiro 实现登录验证功能

    实现登录验证功能 1.创建自己的Realm对象,继承AuthorizingRealm ​    实现父类的doGetAuthenticationInfo 认证方法 MyRealm.java packa ...

最新文章

  1. 科技公司重新关注2级以上驾驶员辅助
  2. RingtoneManager-获得系统当前的铃声
  3. CentOS 6.X 关闭不需要的 TTY 方法
  4. 尺度不变性是指什么不变_不变性如何提供帮助
  5. 终于要来了!苹果明年将推出11英寸版mini-LED屏iPad Pro
  6. 删除xenserver的iso库
  7. Ubuntu系统---C++之Eclipse IDE 编译器安装
  8. 关于php开发中用户请求数据的安全问题的一点想法
  9. kasp技术原理_Massarray技术——中高通量大样本的SNP检测利器!
  10. Android开发-高德地图导航
  11. Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLIntegrityConstraintViolationException:Duplicate entr
  12. 谷歌聘请 macOS 老兵操盘新操作系统 Fuchsia OS
  13. 虚拟打印机直播软件 无人直播互动打印系统 含搭建教程
  14. gamemaker 2 如何做一个过场动画的思路
  15. 豆瓣8.6分的《长安十二时辰》,为什么有人却并不喜欢?
  16. 编写程序,提示用户输入学号、成绩
  17. 回归分析(预测模型)
  18. Java自定义注解-请求限流/防刷
  19. HTML5 Canvas编写五彩连珠(1):预览
  20. BloomFilter怎么用?使用布隆过滤器来判断key是否存在?

热门文章

  1. 有关微信域名被拦截的经验分享
  2. VS开发利器-Visual Assist X
  3. [LUA]中对于文件的操作
  4. SpringBoot内置tomcat出现APR版本过低解决办法
  5. html表单的复选框的值,关于表单:HTML复选框的checked属性的正确值是什么?
  6. AT指令接收短信并编写程序实现
  7. v24.03 鸿蒙内核源码分析(进程概念) | 如何更好的理解进程 | 百篇博客分析HarmonyOS源码
  8. R语言下的frontcon函数,由mean-variance画有效前沿。
  9. 【GitGitHub - 11】:Git合并分支
  10. PicoScenes安装踩坑记录