C#模拟登录普联TP-LINK的AP设备(数据分析之登录篇)

本文详细解析了如何利用浏览器的Web开发者模式分析AP设备登录流程,揭示了登录信息的加密方式,并提供了C#代码实现自动登录的过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、浏览器的“Web开发者”模式

        本例中采用的是“火狐”浏览器,这方面需根据个人喜好。Win10自带的“Microsoft Edge”和Googel谷歌等知名浏览器都有Web开发者模式,只是不同浏览器起的名字不一样。比如Microsoft Edge中是选择菜单工具中的“更多工具——开发人员工具”,而在Googel谷歌浏览器中则是在菜单工具中的“更多工具——开发者工具”。但使用上大致都差不多,不过Googel谷歌的Web开发者模式是全英文。请根据自身情况,选用适合自己的浏览器。

       当然打开Web开发者模式,也有快捷键。请打开浏览器后再打开对应的网站,然后按键盘上的F12键即可。开发者模式调用后,请选择“网络”。如下图所示,后面主要工作就在此界面上操作了。

二、分析网站页面内容

        如上图所示,这是AP设备的登录界面。那么我们如何去获取登录信息,然后采用何种方式将这些信息提交出去完成登录呢。下面我们将进行逐一分析,获取到我们所需的数据。

        首先在开发者模式下,先试着输入登录账号和密码。通过浏览器和服务端的交互,分析一下到底登录前需要传什么数据过去,登录成功后,服务器端返回了些什么东西。

        如下图所示,进行参数对比。所有get方式请求并且带参数的都是明文,这些明文在不同时间是有变化的。所以再结合位数,初步判断为时间戳。而与之对比的post方式请求,则参数是非明文。并且是以post表单数据提交,所以这才是登录信息。

        根据所提交的数据“edp:635118C479049AEED815126B140BAADC”冒号前面为登录用户名并且是明文,而后面则为密码。分析到这里就郁闷了,因为这后面的密码虽然是32位,但绝对不是md5单纯的加密算法。因为经过测试,同样的密码每次登录时这段字符串内容都不一样。并且将密码换成admin或者123这些简单密码的md5值也不一样。所以在分析到这里,好像就无从下手了。但任何网页方式提交数据,一些算法都要借助诸如Javascript这些前端脚本语句。而这些前端内容,在打开对应网页时,就都需加载到本地。因此我们可以查看网页到底调用了那些js文件,看看这些文件中是否有没有相关加密算法。如下图所示,我们可以借助浏览器的源码查看功能,看看登录页面到底调用了那些js文件。

        这下加密方式就找到了,根据代码分析。先将密码明文用md5加密然后再转为大写。接着加上Cookie,但是这里需加一个冒号作为分隔符,然后再将此字符串用md5加密后转为大写即可。注意,代码中的Ext对象是 Ext JS框架,为WEB前端开发框架,目前已经不算主流框架。

三、C#中实现登录

        根据前面的分析,要实现登录必须要服务端给一个Cookie。根据浏览器的开发者模式,采用get方式按照如下访问地址,即可获取到Cookie值。其访问地址是http://10.10.11.24/data/version.json?_dc=1565928793491&option=timeout, 从这个访问地址可以看出,需要带一个时间戳和一个固定参数。

        这里还是借助浏览器的开发者模式,分析一下相关数据。当刷新或打开登录页面时,只有在交互到以上地址时,响应头中才包含Cookie值。实际上用户浏览器端早就有Cookie值,但不知为啥是只有请求头中有Cookie值。这点没找到原因,还望各位看客留言指教。好吧,这里继续。如下图所示,浏览器中响应头中的Cookie值。

注意:请区分响应头和请求头的区别,以下代码段获取Cookie值是从返回头中获取。       

那么产生时间戳就由需要C# 来完成了,其代码如下。

        //产生时间戳
        public static Int64 GetTime()
        {
            Int64 retval = 0;
            var st = new DateTime(1970, 1, 1);
            TimeSpan t = (DateTime.Now.ToUniversalTime() - st);
            retval = (Int64)(t.TotalMilliseconds + 0.5);
            return retval;
        }

        得到时间戳后,就需要get方式提交获取Cookie。get方式获取Cookie代码如下:

        public static void GetCookies(string host, ref string cookies)
        {
            //得到cookies------------------------开始
            string timeStamp = BasicsHelp.GetTime().ToString();
            string urlStr = "http://" + host + "/data/version.json?_dc=" + timeStamp + "&option=timeout";
            PostHelp.HttpGet(urlStr, host, ref cookies);  //获得cookies
            //得到cookies------------------------结束
        }

get方式,如下代码:

public static string HttpGet(string url, string host, ref string cookie)
        {
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = "GET";
                request.Timeout = 10000;
                request.Accept = "*/*";
                request.Host = host;
                request.Referer = "http://"+ host + "/";
                request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0";
                request.Headers.Add("Cookie", cookie);  //将cookie添加到请求头

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                cookie = response.Headers.Get("Set-Cookie");   //获取返回的cookie值。然后返回给调用此函数的对象( ref string cookie)
                if (cookie == null)
                {
                    cookie = request.Headers.Get("Cookie");
                }
                Stream stream = response.GetResponseStream();   //创建一个流,用于接收
                StreamReader reader = new StreamReader(stream, Encoding.GetEncoding("utf-8"));  //创建一个读取流。用于读取接收的流对象
                string retStr = reader.ReadToEnd();   //读取全部返回内容
                reader.Close();
                stream.Close();
                return retStr;
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        根据Cookie值,进行登录。代码如下:

        /// <summary>
        /// 登录AP后台
        /// </summary>
        /// <param name="host"></param>
        /// <param name="cookies"></param>
        /// <returns></returns>
        public static string Login(string host,string cookies)
        {
            //登录----------------------------开始
            string timeStamp = BasicsHelp.GetTime().ToString();
            string url = "http://" + host + "/data/version.json";
            string account = "username";
            string password = "password";
            string cookie = "";
            cookie = cookies.Split(';')[0].Split('=')[1];   //获取cookie验证码
            //根据APP.JS算法制作秘钥------------
            string encoded = BasicsHelp.Getmd5(password).ToUpper() + ":" + cookie;
            encoded = BasicsHelp.Getmd5(encoded).ToUpper();
            string dataStr = "nonce=" + cookie + "&encoded=" + account + "%3A" + encoded + "";

            string strReturn = PostHelp.HttpPost(url, host, dataStr, ref cookies);  //接收登录(POST后服务器)返回信息
            //返回中"status":	0,就表示登录成功
            //注意:若前面登录过,需要等待10000毫米后才能正常登录。否则,"status":	4。
            return strReturn;
        }

借助post进行登录,代码如下:

        /// <summary>
        /// 向指定页面post数据
        /// </summary>
        /// <param name="url">接收网址</param>
        /// <param name="postDataStr">post数据</param>
        /// <param name="cookie">返回的新cookie</param>
        /// <returns>服务器应答内容</returns>
        public static string HttpPost(string url, string host, string postDataStr, ref string cookies)
        {
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
                request.Method = "POST";
                request.Accept = "*/*";
                request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0";
                request.ContentType = "application/x-www-form-urlencoded; charset=UTF-8";
                request.Referer = "http://"+ host + "/";
                request.Host = host;
                string cookie = cookies.Split(';')[0];
                request.Headers.Add("Cookie", cookie);   //将cookie添加到请求头

                byte[] postData = Encoding.UTF8.GetBytes(postDataStr);
                request.ContentLength = postData.Length;   //定义request请求头所带参数内容的长度
                //  ServicePointManager是用于创建、 维护和删除的实例的静态类ServicePoint类。
                //  ServicePoint:提供 HTTP 连接的连接管理
                //  ServerCertificateValidationCallback:SSL证书校验等设置
                ServicePointManager.ServerCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;  //这几个参数都设置为true
                Stream requestStream = request.GetRequestStream();   //存放为流的形式
                requestStream.Write(postData, 0, postData.Length);   //写入流中并发送出去
                requestStream.Close();  //关闭发送流

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();  //用于接收
                Stream responseStream = response.GetResponseStream();   //用流的方式接收
                StreamReader streamReader = new StreamReader(responseStream, Encoding.GetEncoding("utf-8"));  //定义读取流
                string retString = streamReader.ReadToEnd();  //全部读入
                streamReader.Close();   //关闭读入流
                responseStream.Close();  //关闭接收流
                return retString;
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

四、登录成功的返回值

1、借助浏览器分析返回值

如下图所示,登录成功后返回值是json数据。所以在C#中就需要用到json的序列化,然后给予判断是否登录成功。这里就不再重述了,网文很多资料都有。

2、登录成功后想干嘛

登录成功后,主要是在服务端注册或验证Cookie的合法性。后面需要对AP的所有设置都需要带入Cookie值,相关设置实际和登录过程差不多,这里就简化相关内容。

3、如同AC功能一样,实现胖AP模式下的“瘦”模式管理

如下图所示为我做的实例,大致AC的一些功能都具备了。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值