QQ第三方网站授权登陆深入分析及cookie的高级运用

2023-11-03

前言


现如今越来越多的网站采用QQ或微信作为用户的一种快速登陆方式。随着互联网技术的发展,对自动化登陆的要求也随之产生,那么本文就由QQ出发,深入分析下QQ的授权流程,并如何实现自动化登陆。关键代码不分享,仅供参考学习。

首先简单看看QQ第三方网站授权登陆的流程图

简单原理


接触过自动登陆QQ的朋友都知道,最难的就是过验证码,可以参考目前网上例如使用python或者接码平台等方式,但本文的简化这些步骤,服务器的IP多登陆几次成为常用IP后登陆就不需要验证。当然,本文的重点不是QQ登陆,而是如何授权第三方网站。

1、获取需授权的QQ账号信息


  • 如何实现加密验证

使用Fiddler抓包分析登陆流程,重点要解决p参数的加密过程。按F12调试发现以下函数

可看出共使用了TEA、RSA、BASE64一共3种方式混合加密,并且这3种加密函数全由原生JS实现,以上函数使用PHP重写后:

    //16进制字符串转字符串
    public function hexToStr($hex){
    	$str="";
    	$strlen=strlen($hex);
    	for($i=0;$i<$strlen;$i+=2)
    		$str.=chr(hexdec($hex[$i].$hex[$i+1]));
    	return $str;
    } 
    //QQ账号转16进制字符串
    public function QQToHex($str){
        $str=dechex($str);
        for($i = strlen($str);$i < 16; $i ++){
            $str = "0".$str;
        }
        return $str;
    }     
    //QQ登录验证加密函数参数:QQ密码 账号 验证码 是否加密
    public function QQLoginEncrypt($p,$u,$c,$md5="") {
        $hexu= $this->QQToHex($u);// 字符串转hex加密
        $md5p= md5($p);
        $clen= "000".strlen($c);
        $binc= bin2hex(strtoupper($c));
        $key = strtoupper(md5($this->hexToStr($md5p.$hexu)));// MD5加密
        $data= strtoupper($md5p).$hexu.$clen.$binc;
        $EnStr = TEAandRSA($key,$data);//TEA加密 与 RSA加密
        $EnP=base64_encode($this->hexToStr($EnStr)); //BASE64加密
        $EnP=str_replace('/','-',$EnP);
        $EnP=str_replace('+','*',$EnP);
        $EnP=str_replace('=','_',$EnP);
        return $EnP;
    }

其中TEA和RSA的加密因为嫌麻烦就直接用PHP运行js代码了(需要安装v8js扩展)。以下函数的JS代码也是在c_login_2.js中提取的。

  • 模拟用户QQ登陆


    //判断QQ登录方式
    public function CheckQQLoginType(){
        $header=array(
            "Host: ssl.ptlogin2.qq.com",
            "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0",
            "Accept: */*",
            "Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
            "Accept-Encoding: gzip, deflate, br",
            "Connection: keep-alive",
            "Referer: https://xui.ptlogin2.qq.com/cgi-bin/xlogin?appid=716027609&daid=383&style=33&login_text=%E6%8E%88%E6%9D%83%E5%B9%B6%E7%99%BB%E5%BD%95&hide_title_bar=1&hide_border=1&target=self&s_url=https%3A%2F%2Fgraph.qq.com%2Foauth2.0%2Flogin_jump&pt_3rd_aid=101470313&pt_feedback_link=https%3A%2F%2Fsupport.qq.com%2Fproducts%2F77942%3FcustomInfo%3D.appid101470313",
            "Cookie: "
        );
        $url="https://ssl.ptlogin2.qq.com/check?regmaster=&pt_tea=2&pt_vcode=1&uin=".$this->qqnum."&appid=716027609&js_ver=20032614&js_type=1&login_sig=&u1=https%3A%2F%2Fgraph.qq.com%2Foauth2.0%2Flogin_jump&r=0.101003".time()."&pt_uistyle=40";
        $body = $this->curl($url,"","",$header,0);
        //ptui_checkVC('0','!FKE','\x00\x00\x00\x00\x2e\x35\x91\x80','258ae60419e861ea579886ca18f76983b2e77ddf7e870e93b0bd70ab14a6e7637752aafb1de9925d594a7ef70eb3ae2e4e89fda3e181cd63','2', 'uIYUkvs2dy7*m*KdoG6jZu7a6lhs8crUEb8shkSpPT097PMKmhLKdlp-tx4opH1-')
        $data = str_replace("'","",$this->pregjson($body,"ptui_checkVC"));
        $data = str_replace(" ","",$data);
        $data = explode(",",$data);
        return $data;
    }
    //登录QQ账号
    public function LoginQQAccount($data){
        $header=array(
            "Host: ssl.ptlogin2.qq.com",
            "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0",
            "Accept: */*",
            "Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2",
            "Accept-Encoding: gzip, deflate, br",
            "Connection: keep-alive",
            "Referer: https://xui.ptlogin2.qq.com/cgi-bin/xlogin?appid=716027609&daid=383&style=33&login_text=%E6%8E%88%E6%9D%83%E5%B9%B6%E7%99%BB%E5%BD%95&hide_title_bar=1&hide_border=1&target=self&s_url=https%3A%2F%2Fgraph.qq.com%2Foauth2.0%2Flogin_jump&pt_3rd_aid=101470313&pt_feedback_link=https%3A%2F%2Fsupport.qq.com%2Fproducts%2F77942%3FcustomInfo%3D.appid101470313",
            "Cookie: ".$data[8]."; confirmuin=".$data[0]."; ptdrvs=".$data[5]."; ptvfsession=".$data[3]."; ptui_loginuin=".$data[6]
        );
        $url="https://ssl.ptlogin2.qq.com/login?u=".$data[6]."&verifycode=".$data[1]."&pt_vcode_v1=0&pt_verifysession_v1=".$data[3]."&p=".$data[7]."&pt_randsalt=".$data[4]."&u1=https%3A%2F%2Fgraph.qq.com%2Foauth2.0%2Flogin_jump&ptredirect=0&h=1&t=1&g=1&from_ui=1&ptlang=2052&action=2-0-1590368126499&js_ver=20032614&js_type=1&login_sig=&pt_uistyle=40&aid=716027609&daid=383&pt_3rd_aid=101470313&ptdrvs=".$data[5]."&";
        $body = $this->curl($url,"","",$header,1);
        //ptuiCB('0','0','https://ssl.ptlogin2.graph.qq.com/check_sig?pttype=1&uin=775262592&service=login&nodirect=0&ptsigx=9a2a261166dec9d5feb5413d69910a3d7d2b7dd7de9dce096515c193aa68f5bbaef54e72992f558370ade62dbf7db87129e8ce91cda5fd9d7ec34b3b4a4a4a59&s_url=https%3A%2F%2Fgraph.qq.com%2Foauth2.0%2Flogin_jump&f_url=&ptlang=2052&ptredirect=100&aid=716027609&daid=383&j_later=0&low_login_hour=0&regmaster=0&pt_login_type=1&pt_aid=0&pt_aaid=0&pt_light=0&pt_3rd_aid=101470313','0','登录成功!', '皮皮华')
        // return $body;
        $data = str_replace("'","",$this->pregjson($body,"ptuiCB"));
        $data = str_replace(" ","",$data);
        $data = explode(",",$data);
        return $data;
    }
    //获取QQ登录成功后的p_skey
    public function QQLoginGetPskey($url){
        $json=$this->curl($url,"","",array(),1);
        list($header, $body) = explode("\r\n\r\n", $json,2);
        preg_match('/Set-Cookie: p_skey=(.*);(.*)graph.qq.com/iU',$header,$str); //正则匹配
        $data = "pt_login_type=1; p_skey=".$str[1];
        $this->g_tk=$this->getGTK($str[1]);
        if(strlen($str[1]) < 1){
            $this->code= 202;
            $this->msg="获取登录p_skey的Cookie值失败";
            return $json;
        }
        preg_match('/Set-Cookie: p_uin=(.*);(.*)graph.qq.com/iU',$header,$str); //正则匹配
        $data= $data . "; p_uin=" .$str[1];
        if(strlen($str[1]) < 1){
            $this->code= 202;
            $this->msg="获取登录p_uin的Cookie值失败";
            return $json;
        }
        preg_match('/Set-Cookie: pt4_token=(.*);(.*)graph.qq.com/iU',$header,$str); //正则匹配
        $data= $data . "; pt4_token=" .$str[1];
        if(strlen($str[1]) < 1){
            $this->code= 202;
            $this->msg="获取取登录pt4_token的Cookie值失败";
            return $json;
        }
        $this->code= 200;
        $this->msg="获取登录Cookie值成功";
        $this->cookie = $data;
        file_put_contents("authqq.json",json_encode($data));
        return $json;
    }
    //重新获取QQ授权Cookie
    public function GetAuthCookie(){
        $data = $this->CheckQQLoginType();
        if($data[0] == "0"){//免密登录
            $data[6] = $this->qqnum;
            $data[7] = $this->QQLoginEncrypt($this->qqpwd,$this->qqnum,$data[1]);//P参数加密
            $logindata = $this->LoginQQAccount($data);
            if($logindata[4]=="登录成功!"){
                $this->QQLoginGetPskey($logindata[2]);
            }
        }
        return $data;
    }

2、怎样授权第三方网站并拿到第三方网站的cookie


同样使用Fiddler抓包分析登陆流程,整个过程分3步走。

    //获取第三方网站Cookie
    public function GetSiteCookie($sitename){
        $state= "";
        if(strlen($this->site[$sitename]["loginurl"]) > 1){
            $state = $this->GetState($sitename);//获取state
        }
        $url = $this->authorize($sitename,$state);//授权第三方网页
        if($this->code == 200){
            return $this->GetUrlCookie($sitename,$url);//获取回调网页Cookie
        }
    }

1)获取state

某些网站在接入Oauth2.0时并没有做state验证,所以也不需要此步骤。以下以网易云音乐为例。

        "pph_music163" => array(
                    "name" => "网易云音乐",//网站名称
                    "loginurl" => "https://music.163.com/api/sns/authorize?snsType=5&clientType=web2&callbackType=Login&forcelogin=true",//State获取url
                    "redirect_uri" => "https%3A%2F%2Fmusic.163.com%2Fback%2Fqq",//回调地址
                    "client_id" => "100495085",//网易云网站对应的ID
                    "cookielist" => array("MUSIC_U" => ""),//需要获取的Cookie值
                    "cookieignorelist" => array(),
                    "cookieTime" => 1267200,//24*60*60*15-8*60*60, Cookie有效时长,单位秒
                    "cookieEndTime" => 0  //cookie到期时间
                ),

通过Fiddler找到网易云音乐对应获取state的url:https://music.163.com/api/sns/authorize?snsType=5&clientType=web2&callbackType=Login&forcelogin=true

模拟请求该链接后通过正则匹配获取state的值。

2)授权第三方网页

通过POST请求https://graph.qq.com/oauth2.0/authorize传入最重要的client_id、redirect_uri、state、g_tk这4个参数,其中g_tk由p_skey计算得出。如果授权成功则会返回授权成功后的回调url。

3)获取回调网页Cookie

模拟请求上一步获取到的回调url即可获取到对应网站的cookie信息。

总结

通过以上流程即可全自动化的实现登录,并且可以在此基础上增加cookie到期时间判断,实现定时更新第三方网站的cookie。

以下为PHP版完整的第三方授权类,

本文仅供思路参考,严禁用于非法用途,转载请注明出处。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

QQ第三方网站授权登陆深入分析及cookie的高级运用 的相关文章

  • python 脚本中 os.system 的 256 和 512 响应代码是什么

    当我在 python 中使用 os system ping 服务器时 我得到多个响应代码 使用的命令 os system ping q c 30 s SERVERANME 0 在线 256 离线 512 512 是什么意思 Per the
  • WAMP 不显示目录列表中的图标

    过去 我通过 vmware 处理 PHP 代码 但最近我决定转而通过 WAMP 在 Windows 8 1 上 在本地进行处理 我创建了一个空文件夹tests in the www folder 然后在我的浏览器上输入http localh
  • 在 vim 折叠线中语法高亮 Python

    我发现代码折叠 http en wikipedia org wiki Code folding帮助我更好地组织我的文件 因此 在我的底部 vimrc 我启用vim代码折叠 http vimdoc sourceforge net htmldo
  • 类型错误:需要 Future 或协程

    我尝试在 asyncssh 上自动重新连接 ssh 客户端 SshConnectManager 必须留在后台并在需要时进行 ssh 会话 class SshConnectManager object def init self host u
  • 使用 3d 对象作为 3d 散点图中的标记 - Python

    使用下面的代码 我尝试模拟一个用罐头制成的碗 我希望每个标记都是一个罐头 最好的方法是什么 我真的很感激任何建议 谢谢 import pylab import numpy as np from math import pi sin cos
  • 使用 python 只读取 Excel 中的可见行

    我想只读取 python 中 Excel 工作表中的可见行 输入 Excel表 所以当我过滤时 作为 python 中的输出 在本例中我将仅获得可见数据 1 行 这是我的代码 from openpyxl import load workbo
  • 将秒转换为天、小时、分钟和秒

    我想转换一个变量 uptime这是秒 分为天 小时 分钟和秒 Example uptime 1640467 结果应该是 18 days 23 hours 41 minutes 这可以通过以下方式实现DateTime http php net
  • Python,多线程,获取网页,下载网页

    我想在一个站点批量下载网页 我的 urls txt 文件中有 5000000 个 url 链接 大约有300M 如何让多线程链接这些网址并下载这些网页 或者如何批量下载这些网页 我的想法 with open urls txt r as f
  • 使用 php 和 symfony 从数组创建 Excel 文件

    我正在尝试使用 PHP 和 symfony 将数组导出为 XLS 文件 如下面的代码所示 创建 XLS 文件后 我只能获取数组的最后一行 并且它显示在文件的第一行中 似乎 lignes 变量没有增加 我不明白出了什么问题 有人可以帮忙吗 f
  • ZF2 工厂获取参数

    我有一个动态类别导航 在导航工厂中 我想从路线获取参数 我怎样才能做到这一点 在我看来 在我的 module php 中 public function getServiceConfig return array factories gt
  • 如何在数据框中绘制包含三列的无向图,形成 3 种不同类型的节点(三方)?

    我正在尝试使用三个不同的列表绘制网络的可视化 这三个列表形成 3 种类型的节点 下面的代码正在运行 如图所示 需要两个列表 用户 ID 评分 但是 我希望我的图表是三部分的 即 user userId review ratings prod
  • 需要使用 php 从远程服务器下载与 $_FILES 相同的内容[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 好的 我有处理图像上传的 php 代
  • 无需下载整个文件即可读取 ID3 标签

    是否可以读取 MP3 文件的 ID3 标签 持续时间 艺术家 标题 而无需下载整个文件 我做了一些测试 只需下载 MP3 文件的几个字节就可以获得艺术家和标题标签 但我不确定持续时间和其他标签是否可能 Thanks 我刚刚发现 ffmpeg
  • 如何修改 contenteditable 元素的innerHTML

    我使用 Selenium 与 Chrome driver 和 python3 6 来测试网站 我在网页中有代码片段如下 div class 3F6QL 2WovP div class 39LWd Type a message div div
  • 如何加速 pandas 字符串函数?

    我正在使用 pandas 矢量化 str split 方法来提取从 上的拆分 返回的第一个元素 我还尝试使用 df apply 与 lambda 和 str split 来产生等效的结果 使用 timeit 时 我发现 df apply 的
  • 如何使用 PDO 动态构建查询

    我正在使用 PDO 并想做这样的事情 query dbh gt prepare SELECT FROM table WHERE column value query gt bindParam table tableName query gt
  • 如何将 fields 参数传递到 Google Drive Python API 调用中

    I have results drive service files list body execute where body q query string maxResults 1 为了提高性能 我想限制返回的字段 如下所述 https
  • 转换MAC地址格式

    我刚刚编写了一个小脚本 从交换机中提取数百个 MAC 地址进行比较 但它们的格式为 0025 9073 3014 而不是标准的 00 25 90 73 30 14 我对如何转换它感到困惑 我能想到的最好的办法就是在 处将它们分解成碎片 然后
  • sqlsrv_num_rows 不返回任何值

    我正在尝试获取查询中返回的行数 while 循环遍历结果有效 但由于某种原因 sqlsrv num rows 不返回任何值 result SELECT from dtable WHERE id2 apple query sqlsrv que
  • 如何显示不同页眉的页面? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我正在为我的学校项目开发网站 但我遇到了一个问题 我在每个页面上显示一个标题 我的标题之一包含登录表单 另一标题包含用户名 搜索栏等 问题是

随机推荐

  • Magisk模块开发指南

    BusyBox Magisk整合了功能完整的BusyBox二进制文件 包括对SELinux的完整支持 执行文件位于 data adb magisk busybox Magisk的BusyBox支持运行时可切换的 ASH Standalone
  • ffmpeg基础五:单独解码裸流aac或MP3或H264

    av parse parse2 用于从输入的数据流中将流中的压缩编码数据一帧一帧的分离出来 也就是从一端数据码流中将需要解码的packet读取出来 由于H264由特殊的格式组成 StartCode NALU Header NALU Payl
  • Python - 实现logging根据日志级别输出不同颜色

    文章目录 一 完整代码 二 代码解释 三 附 自定义颜色对应代码 前段时间因为工作需要脚本打印不同颜色的日志 查找了网上的一些方法 大部分都需要再安装第三方模块 后来选择采用比较简易的办法 类似于print 函数自定义内容颜色 这种方式的缺
  • 14、mysql底层知识进阶-MySql中常用工具:mysqladmin、mysqlbinlog、mysqldump、mysqlimport、mysqlshow

    目录 1 MySql中常用工具 1 1 mysql 1 1 1 连接选项 1 1 2 执行选项 1 2 mysqladmin 1 3 mysqlbinlog 1 4 mysqldump 1 5 mysqlimport source 1 6
  • Qt 软件开发框架(详细版)

    该文章用图例 代码方式演示了 一个线上软件基本框架 精简 开发工具Qt VS2015 一 基本要素 这里会用简单的图例和完整代码 这里以Qt代码为例 说明一个线上软件基本的框架 一个线上windows软件 一般分为几个大的部分 1 UI模块
  • 什么是性能测试?

    什么是性能测试 什么是性能测试 压力测试软件性能测试是一种测试类型 旨在确定系统的性能以衡量性能 验证或验证系统的质量属性 例如在各种负载条件下的响应性 速度 可伸缩性 稳定性 在混合负载条件下对系统进行了测试 并检查了系统在各种工作负载下
  • 空洞卷积aspp 学习笔记

    ASPP 以下内容转自 空洞空间卷积池化金字塔 atrous spatial pyramid pooling ASPP 对所给定的输入以不同采样率的空洞卷积并行采样 相当于以多个比例捕捉图像的上下文 上图为deeplab v2的ASPP模块
  • Oracle 表碎片检查及整理方案

    作者 JiekeXu 来源 公众号 JiekeXu DBA之路 ID JiekeXu IT 大家好 我是 JiekeXu 很高兴又和大家见面了 今天和大家一起来看看 Oracle 表碎片检查及整理方案 欢迎点击上方蓝字关注我 标星或置顶 更
  • GitHub个人Blog完全攻略

    Git个人网站完整攻略 当前越来越多的大牛转战GitHub的时候 我们也应该考虑搭建自己的一个Blog来记录自己的学习和成长经历了 一则 作为未来的码农是需要自己与国际 至少是与主流的代码托管相接触的 二则 我想自己在校的时光也许需要重新好
  • Nvidia Video Codec SDK——AppDecImageProvider动态模糊

    Nvidia Video Codec SDK AppDecImageProvider动态模糊 cpp文件 cu文件 核函数focalLength 获得注视点对应深度 核函数Bgra32ToSmooth cpp文件 初始化变量 平滑函数Bgr
  • Web 中间件漏洞

    1 Tomcat Tomcat是Apache Jakarta软件组织的一个子项目 Tomcat是一个JSP Servlet容器 它是在SUN公司的JSWDK Java Server Web Development Kit 基础上发展起来的一
  • 2022全年度冰箱十大热门品牌销量榜单

    自2022年年初以来 各地纷纷部署支持包括冰箱在内的家电大宗消费政策措施 其中家电补贴政策是刺激家电消费的主旋律 宏观经济政策环境改善 利好冰箱行业的长期发展 根据鲸参谋数据统计 今年京东平台冰箱的年度累计销量达到1400多万件 同比增长1
  • python网络爬虫--项目实战(1)--500px图片爬取

    一 目标 爬取500px图片并保存 目标网址 https 500px com cn community discover 二 分析 2 1 网站分析 经过研究发现该网站没有点击下一页的按钮 然后往下拖动下拉条直到最后 会自动刷新出新的内容
  • 机器学习加强-随机森林

    一 概述 1 1 集成算法概述 集成学习 ensemble learning 是时下非常流行的机器学习算法 它本身不是一个单独的机器学习算法 而是通 过在数据上构建多个模型 集成所有模型的建模结果 目标 集成算法会考虑多个评估器的建模结果
  • 使用Aardvark(Total Phase)监测I2C链路

    使用Aardvark监测I2C链路 项目调试实例 1 Aardvark是Total phase公司推出的一款I2C SPI总线的调试工具 其功能包括 作为主 从设备调试I2C或SPI的相关功能 监测I2C总线上的数据 调试GPIO端口等 2
  • 请求分页内存管理的模拟 c++代码_C开发实战-内存管理

    作用域和变量 作用域就是作用的范围 当定义变量时不同作用域的变量位于不同的内存空间 变量按照不同的作用域可以分为局部变量和全局变量 而局部变量和全局变量都可以使用static修饰 static修饰的局部变量叫静态局部变量 static修饰的
  • Android Studio快捷键失效的问题及实用快捷键汇总

    Android Studio快捷键失效的问题及实用快捷键汇总 如题 如果你的Android studio快捷键失效了 并且检查了编辑器 没有动过配置 那么你的快捷键就是冲突了 例如QQ 输入法 音乐播放器等 一般情况下打开正在使用的软件的设
  • 关于对java项目中应用分层的简单理解

    一 基于springboot的逻辑分层结构 1 概念定义 大部分来自于 https blog csdn net weixin 39781363 article details 112028431 1 PO 和数据库表对应 Persistan
  • Windows环境使用VSCode 调试Linux环境C/C++代码

    在Win10中 配置VScode调试Linux环境下的C语言的代码 配置过程不太常用 特此记录下 1 源码文件 都一样 怎么写看个人爱好 2 VSCode安装这里也不做赘述 VSCode默认安装好是使用的英文 想要中文界面 可以在扩展中安装
  • QQ第三方网站授权登陆深入分析及cookie的高级运用

    前言 现如今越来越多的网站采用QQ或微信作为用户的一种快速登陆方式 随着互联网技术的发展 对自动化登陆的要求也随之产生 那么本文就由QQ出发 深入分析下QQ的授权流程 并如何实现自动化登陆 关键代码不分享 仅供参考学习 首先简单看看QQ第三