c++协议解析 (c语言协议详解)

项目背景:

近期有朋友想让我帮他实现一个自动登录qq空间,并实现自动点赞,评论,留言之类的功能。正好闲来无事,研究一下实现方法。

实现方法:

要实现此功能其实很简单,无非就是登录成功后获取到cookie,然后通过get、post方式请求功能接口。

大致思路:

  1. get方式请求获取登录二维码接口,并拿到二维码图片(这里为什么要选择用二维码方式登录呢,因为扫码方式最简单,账号密码登录时会有滑块验证,有时还会有设备锁验证)
  2. 每隔1秒或2秒调用接口来监听二维码状态
  3. 当监听到登录成功后取出cookie,此时响应里有一个url,我们把它取出来并跳转到这个路径(需要禁止重定向)

好了,介绍完毕,下面来实际操作吧

新建一个winform程序,在窗体上放一个PictureBox控件用来展示二维码

协议登录和脚本登录,协议登录

在窗体加载事件中,我们来获取二维码

private void Form1_Load(object sender, EventArgs e)
{
      //1、GET方式请求二维码图片      
      HttpWebRequest request = HttpWebRequest.CreateHttp("https://ssl.ptlogin2.qq.com/ptqrshow?appid=549000912&e=2&l=M&s=3&d=72&v=4&t=0.6676227813796067&daid=5&pt_3rd_aid=0");
      request.Method = RequestMethod.GET;
      request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36";
      //2、得到响应消息
      WebResponse response = request.GetResponse();
      //3、拿到响应消息中的头部信息中的Set-Cookie值(用于计算ptqrtoken)
      WebHeaderCollection headerCollection = response.Headers;
      Cookie.cookie1 = headerCollection.Get("set-cookie");
      //4、拿到二维码图片,然后把这个图片展示在窗体中
      Stream stream = response.GetResponseStream();
      Image image = Image.FromStream(stream);
      //5、展示在窗体中
      login_qrcode.Image = image;
  
  				//异步监听二维码状态
            Task task = new Task(() =>
            {
                while (true)
                {
                    if (ListenLoginStatus())
                    {
                        break;
                    }
                    Thread.Sleep(1000);
                }
            });
            task.Start();
}

二维码获取成功后,需要监听二维码状态(共四个状态:二维码未失效、扫描未确定登录、已确定登录、二维码已失效)

用户扫描窗体上的二维码图片,并确认登录后,就停止监听二维码并得到登录成功的cookie,拿到cookie后,就可以进行一系列的操作了,比如。。。再比如。。。自己想去吧

				/// <summary>
        /// 监听二维码状态 登录成功返回true
        /// </summary>
        public bool ListenLoginStatus()
        {
            //1、计算出必要的参数ptqrtoken
            ///////    这里的cookie1值是获取二维码接口响应体中的set-cookie
            string ptqrtoken = ptqrtoken(Cookie.cookie1.Split(';')[0].Split('=')[1]);
            //2、请求二维码状态
            string url = "https://ssl.ptlogin2.qq.com/ptqrlogin";
            url += "?u1=https://qzs.qq.com/qzone/v5/loginsucc.html?para=izone";
            url += "&ptqrtoken=" + ptqrtoken;
            url += "&ptredirect=0";
            url += "&h=1";
            url += "&t=1";
            url += "&g=1";
            url += "&from_ui=1";
            url += "&ptlang=2052";
            url += "&action=0-0-" + DateUtil.GetTimeStamp2();   // 获取当前时间戳(毫秒级)
            url += "&js_ver=20021917";
            url += "&js_type=1";
            url += "&login_sig=";
            url += "&pt_uistyle=40";
            url += "&aid=549000912";
            url += "&daid=5";
            HttpWebRequest request = HttpWebRequest.CreateHttp(url);
            request.Method = RequestMethod.GET;
            request.Headers.Add("cookie", Cookie.cookie1);
            WebResponse response = request.GetResponse();
            string result = "";
            using (Stream stream = response.GetResponseStream())
            {
                using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
                    result = reader.ReadToEnd().ToString();
            }
            if (!(result.Contains("http") && result.Contains("登录成功")))
                return false;

            //登录成功后,取出用户昵称
            string[] arrayResult = result.Replace("ptuiCB(", "").TrimEnd(')').Split(',');
            UserNickName = arrayResult[arrayResult.Length - 1].Trim().Trim('\'');

            //登录成功后,取出cookie
            Cookie.cookie2 = response.Headers.Get("set-cookie");

            //扫码登录成功后,会返回一个路径,跳转到这个路径后,取出cookie
            url = arrayResult[2].Trim().Trim('\'');
            request = HttpWebRequest.CreateHttp(url);
            request.Method = RequestMethod.GET;
            //必须禁用重定向,否则会自动重定向到别的网址,就无法取到cookie
            request.AllowAutoRedirect = false;
            response = request.GetResponse();
            Cookie.cookie3 = response.Headers.Get("set-cookie");

            //取出登录成功的qq号码
            string[] _a = url.Split('&');
            foreach (string item in _a)
            {
                if (item.IndexOf("uin=") == 0)
                {
                    UserQqNumber = item.Replace("uin=", "");
                    break;
                }
            }

            //访问个人中心
            request = HttpWebRequest.CreateHttp("https://user.qzone.qq.com/" + UserQqNumber);
            request.Method = RequestMethod.GET;
            request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.117 Safari/537.36";
            //p_skey用于计算g_tk
            string p_skey = "";
            string[] arrayCookie = Cookie.cookie3.Replace(";,", ";").TrimEnd(';').Split(';');
            foreach (string item in arrayCookie)
            {
                if (item.IndexOf("uin=") == 0)
                    Cookie.cookie4 += item + "; ";
                if (item.IndexOf("skey=") == 0)
                    Cookie.cookie4 += item + "; ";
                if (item.IndexOf("p_uin=") == 0)
                    Cookie.cookie4 += item + "; ";
                if (item.IndexOf("p_skey=") == 0)
                {
                    Cookie.cookie4 += item + "; ";
                    if (!(item.IndexOf("p_skey_forbid") == 0) && !item.Equals("p_skey="))
                        p_skey = item.Replace("p_skey=", "");
                }
            }
            if (!string.IsNullOrWhiteSpace(Cookie.cookie4))
                Cookie.cookie4 = Cookie.cookie4.Trim().TrimEnd(';');
            request.Headers.Add(Header.cookie, Cookie.cookie4);
            response = request.GetResponse();            

            return true;
        }

        /// <summary>
        /// 计算ptqrtoken
        /// 用于监听二维码状态
        /// </summary>
        public string ptqrtoken(string qrsign)
        {
            int e = 0;
            for (int i = 0; i < qrsign.Length; ++i)
            {
                e += (e << 5) + (int)(char)(qrsign[i]);
            }
            return e+ "";
        }

这边文章到这里就结束了,主要介绍了如何实现通过扫描二维码来登录qq空间,后续的别的操作(点赞评论)下次再说