C# 模拟登录

原理html

咱们知道,通常须要登陆的网站,服务器和客户端都会有一段时间的会话保持,而这个会话保持是在登陆时候创建的, 服务端和客户端都会持有这个KEY,在后续访问时,都须要核对这两个KEY是否一致。 而客户端的这个KEY就存在cookie中。 所以,咱们须要获取登陆后的cookie值,并在后续的访问中,都添加这个cookie。这样才能作到模拟登陆的效果。chrome

 

例子:服务器

咱们以获取博客园首页的园龄为例。须要作三步cookie

1. 模拟登陆博客园session

2. 构建我的主页的Request请求,包括cookieapp

3. 获取我的主页的数据后, 分析页面,并获取园龄的数据。工具

代码以下:post

复制代码
static void Main(string[] args)
        {
            //string html= Hello();
            string html = LoginSimulation();
            Console.WriteLine(html);
            Console.Read();
        }
 static string LoginSimulation()
        {
            
            string url = "https://passport.cnblogs.com/user/signin";
            string postData = "{\"input1\":\"MvxmwEWfUF26IvKNa1dUiZn1xmSBhNW0wJyoaUlDPXoh+Mb+z2eZK3r3c9Jd0aT0/Wzz3ht7LMeTllu8ISY9nfQIuKB0C19Y9/IfKYSktpZZOVaKx/XP3i/mGxXC3K5m2la91ViRh3BO36xT4E98dbqVHPtynjuNafuVIBF5a2M=\",\"input2\":\"xxxx":false}";

            //1.获取登陆Cookie
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(url);
            req.Method = "POST";// POST OR GET, 若是是GET, 则没有第二步传参,直接第三步,获取服务端返回的数据
            req.AllowAutoRedirect = false;//服务端重定向。通常设置false
            req.ContentType = "application/x-www-form-urlencoded";//数据通常设置这个值,除非是文件上传

            byte[] postBytes = Encoding.UTF8.GetBytes(postData);
            req.ContentLength = postBytes.Length;
            Stream postDataStream = req.GetRequestStream();
            postDataStream.Write(postBytes, 0, postBytes.Length);
            postDataStream.Close();

            HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
            string cookies = resp.Headers.Get("Set-Cookie");//获取登陆后的cookie值。

            //2.登陆想爬取页面的构造,主要多一个Cookie的构造
            string contentUrl = "https://home.cnblogs.com/u/xinjian/";
            HttpWebRequest reqContent = (HttpWebRequest)WebRequest.Create(contentUrl);
            reqContent.Method = "GET";
            reqContent.AllowAutoRedirect = false;//服务端重定向。通常设置false
            reqContent.ContentType = "application/x-www-form-urlencoded";//数据通常设置这个值,除非是文件上传

            reqContent.CookieContainer = new CookieContainer();
            reqContent.CookieContainer.SetCookies(reqContent.RequestUri, cookies);//将登陆的cookie值赋予这次的请求。

            HttpWebResponse respContent = (HttpWebResponse)reqContent.GetResponse();
            string html = new StreamReader(respContent.GetResponseStream()).ReadToEnd();

            //3. 分析读取该页面的数据,可使用HtmlAgilityPack第三方类,这里比较简单,本身写个获取方法就行
            string age= GetVal(html, "<span title='入园时间:2010-6-28'>", "</span>");
            return age;
        }
复制代码

 

注意事项网站

 1. 本次模拟登陆,我发现chrome的开发人员工具,并无抓到真正的Post包,和我以前遇到的状况同样, 后来仍是使用了httpwatch后,才抓到了真正的数据包。博客园作的不错,提交的数据进行了加密。 固然个人密码我也已经改为了XXX,用户须要运行的话,须要自行抓包获取对应的postData。编码

 

2. 针对cookie的赋值,主要由这两句完成

            reqContent.CookieContainer = new CookieContainer();
            reqContent.CookieContainer.SetCookies(reqContent.RequestUri, cookies);//将登陆的cookie值赋予这次的请求。

可是据说C#封装的不是很好,有时候会漏掉数据,但我目前还没遇到过, 若是遇到,须要将cookie的string手工转换成CookieCollection,并赋予CookieContainer。

 

3. 针对ASP.NET的网页, 会存在__VIEWSTATE & __EVENTVALIDATION 这两个post字段, 对于没创建会话时,这两个值是不会变的,而一旦创建会话(模拟登录后),每次访问的页面,这两个值都会改变, 解决办法是先使用GET获取该页面的数据后,获取这两个字段的值, 而后在post的时候,进行赋值。 

 

4. 在遇到500错误的时候,说实话,我也很头疼,不知道如何调试,但我总结下来,必定是request构建的不对。主要查看以下问题:

  4.1. 对比post的数据的key和value,看看格式是否正确,如是否进行了编码 WebUtility.UrlEncode()。 

  4.2. 对比post的数据的,是否Post了所有的数据, 固然这里不光是当前页面,有时候还会用到其余页面,我举个例子, 我在订单页面上传附件, 在附件上传页面,发现并无Post订单的id,那么这个时候,就须要查找订单的id服务端是何时获取的,这个时候就须要猜了,有多是在打开订单页面的时候,服务端就把此id存储到session中了。因此先须要模拟打开订单页面,而后在模拟订单附件上传的post。

  4.3 注意是是否犯了__VIEWSTATE & __EVENTVALIDATION的错误,注意,针对数据型的post,须要进行urlEncode。

  4.4 Request的Head是否构建全了, 有时候客户端会提交自定义的head,注意查看。同时UserAgent有时候也会须要进行变化,但目前我还没遇到过。

  4.5. 若是肯定Post的数据全了,而且仍是500错误的话,考虑下是否cookie有问题,虽然我还没遇到过。

相关文章
相关标签/搜索