之前没做过给网站接入谷歌身份验证器,记录一下。
概念纠正
我之前一直以为谷歌身份验证器是联网的,需要从谷歌获取动态验证码,或者从接入的网站通信获取。
实际的运行原理应该是:
- 用户从网站申请开启双因素验证(2FA,两步验证)
- 网站生成秘钥并存储
- 网站将秘钥展示给用户
- 用户使用谷歌身份验证器扫码或自行保存
之后网站就可以对开启的用户进行双因素验证了。实际网站和用户之间的动态密码,并不是通信获取的,而是双方都是使用TOTP算法 对秘钥,进行计算,获得的动态密码。
实现
目前手上这个需要加双因素验证的网站是php的,于是好玩的一幕来了,我翻遍了谷歌官网都没找到相关的内容,能找到的都是第三方的实现,不知道是怎么回事。
找到的第三方实现的库:https://github.com/antonioribeiro/google2fa
剩下的似乎也没多少好说的,就是引入库,然后按着上方的流程做就可以了。
生成
1// 引入 google2fa2// ...3
4// 生成秘钥5$secret = google2fa::generateSecretKey(32);6
7// 持久化保存$secret8// ...9
10// 生成二维码链接11$qrCodeUrl = google2fa::getQRCodeUrl(12 '[公司名或网站名]',13 '用户名称或邮箱',14 $secret15);7 collapsed lines
16
17// 展示二维码给用户 这里用的是 phpqrcode18$QR_base64 = QRcode::png($qrCodeUrl, false, 'Q', 6, 1);19$image_qr = imagecreatefromstring(base64_decode($QR_base64));20
21Header("Content-type: image/png");22ImagePng($image_qr);验证用户的动态密码
1// $code 为用户提交的动态验证码2// $secret 为服务器保存的秘钥3$res = google2fa::verifyKey($secret, $code, 0); // 这里的0需要注意一下 后面细说4if($res!==FALSE){5 echo 'ok';6}else{7 echo 'no';8}上面的0,在文档里 Validation Window,这里感觉应该理解为验证时间窗口。默认为4,每30秒生成一个新动态码,4个就是4 * 30,2分钟,因此一个动态码验证窗口包含前2分钟和后2分钟。
主要是怕服务器时间与身份验证器时间有误差,可以做一定兼容。