互联网古早时期,有很多大型网站都被爆库过,包括腾讯网(qq的爸爸),网易,csdn等等,当时这些网站的密码甚至是明文保存,后续才有了加盐(salt)后,取MD5值这样的二次加密的方式。同时,也出现了类似谷歌二次验证
Google Authenticator」这样的二次验证方式,类似的还有微软Authenticator
APP、腾讯的QQ安全中心(计算动态码使用自己的算法),能访问到我写的这篇文章的您,一定是了解这个东西的。今天就重点讲一讲怎么将谷歌二次验证功能迁移到QQ
robot里面,不安装APP来实现相应的功能。

准备工作

QQ机器人实现原理讲解

流程示意图

qq机器人实现谷歌二次验证码流程示意图

用户使用路径

  1. 用户访问网站/APP时,需要使用二次验证结果
  2. 给QQ机器人(电报机器人/微信机器人等等)发送触发关键词,如:ga xx_site
  3. qqrobot识别到需要使用谷歌二次验证码了,读取本地或者数据库内xx_site初始的动态密钥
  4. 使用php GoogleAuthenticator class计算结果
  5. 将计算的动态ga二次验证码以qq消息的方式发送给用户
  6. 用户使用ga code,访问网站或者APP

实现ga二次验证核心代码

实现功能清单

  • 添加谷歌二次验证码
  • 删除ga二次验证
  • 获取Google Authenticator / 微软 Authenticator 等APP,扫码添加二次验证的二维码功能「恢复使用验证APP时需要」
  • ga code计算
// print_r($array);
$s = str_ireplace(array('ga',' '), '', $array["message"]);
$arr = explode(",", $s);

$content = "";
$imagepath = '';
$type = 0;

// 加入验证码有效时间
$sec = date('s');
$sec = $sec > 30 ? 60 - $sec : 30 - $sec;
if($sec == 0){
    $sec = 30;
}

//添加key
if(count($arr) == 3){
    if($arr[0] == "add"){
        if(file_put_contents("config/ga/" . $arr[1] . ".json", json_encode(array("account" => $arr[1], "key" => $arr[2])))){
            $config = json_decode(file_get_contents("config/ga/" . $arr[1] . ".json"), true);
            $ga = new PHPGangsta_GoogleAuthenticator();
            //要计算的key
            if(isset($config["key"]) && isset($config["account"])){
                $secret = $config["key"];
                $oneCode = $ga->getCode($secret);
                $content = "添加成功,CODE:" . $oneCode;
                $type = 1;
            }
        }
    }
}

if(count($arr) == 2){
    //删除key
    if($arr[0] == "del"){
        if(is_file("config/ga/" . $arr[1] . ".json")){
            if(unlink("config/ga/" . $arr[1] . ".json")){
                $content = "删除成功";
                $type = 1;
            }
        }
    }
    
    //生成QR
    if($arr[0] == "qr"){
        $config = json_decode(file_get_contents("config/ga/" . $arr[1] . ".json"), true);
        //要计算的key
        if(isset($config["key"]) && isset($config["account"])){
            // echo "Key: ".$secret."\n\n";
            $url = 'otpauth://totp/' . $config["account"] . '?secret=' . $config["key"];
            $content = "[CQ:image,file=https://xiao.nu/apis/qr/?size=24&level=L&t=" . time() . "&data=" . urlencode($url) . ",type=show,id=40000]";
            $type = 2;
        }
    }
}

//发送code
if(is_file("config/ga/" . $s . ".json")){
    $config = json_decode(file_get_contents("config/ga/" . $s . ".json"), true);
    $ga = new PHPGangsta_GoogleAuthenticator();
    //要计算的key
    if(isset($config["key"]) && isset($config["account"])){
        $secret = $config["key"];
        // echo "Key: ".$secret."\n\n";
        $oneCode = $ga->getCode($secret); //服务端计算"一次性验证码"
        $content = $oneCode;
        $type = 1;
    }
}

$user_id = $array["user_id"];

if($type > 0){
    $wdata = array(
        "user_id" => $user_id,
        "message" => $content . "-" . $sec,
        "group_id" => '',
        'auto_escape' => "false"
        
    );
    // var_dump($wdata); 
    // die();
    // 使用 cq-http 接口发送文本消息
    postData("http://localhost:" . $Port . "/SendPrivatecontent", $wdata);     
}else{
    die();
}
}

以上为通篇的内容,如果自行尝试的时候有什么问题的话,可以在文末留言。