实现此功能首先需要借助一些抓包工具,对相应的网站登陆过程进行分析,此过程根据网站的不同,可能复杂,也可能很简单。常用的抓包工具FF下FireBug和IE下的HttpWatch.这两个工具很强大,以此工具获取的信息足以应对C#模拟网站登陆过程所需要的信息。抓包工具的使用教程网上很多,例如FireBug教程,在此就不做过多介绍。当然网上C# C/S结构模拟网站登陆信息也很多,但基本都是代码片段或是逻辑很复杂。所以把我实践的过程写下来与大家分享。此实验过程是基于模拟登陆校内而完成的。
首先使用FireBug 获取登陆相关信息,在点登陆之前先把FireBug中信息清除,这样获取的信息就从点击登陆按钮后开始,以便后续分析,如下图:
每次请求与下一次请求之间的联系就是每次请求后返回的Cookies数据,前一次的返回Cookie数据需要同下一次请求一同发送到服务器,这也是C#模拟网站登陆的关键。详见以下逻辑代码:
View Code
1 using System; 2 using System.Collections.Generic; 3 using System.IO; 4 using System.Linq; 5 using System.Net; 6 using System.Text; 7 using System.Threading.Tasks; 8 using System.Windows.Forms; 9 10 namespace WebHelp 11 { 12 public class WebAutoLogin 13 { 14 #region 属性 15 /// <summary> 16 /// 登陆后返回的Html 17 /// </summary> 18 public static string ResultHtml 19 { 20 get; 21 set; 22 } 23 /// <summary> 24 /// 下一次请求的Url 25 /// </summary> 26 public static string NextRequestUrl 27 { 28 get; 29 set; 30 } 31 /// <summary> 32 /// 若要从远程调用中获取COOKIE一定要为request设定一个CookieContainer用来装载返回的cookies 33 /// </summary> 34 public static CookieContainer CookieContainer 35 { 36 get; 37 set; 38 } 39 /// <summary> 40 /// Cookies 字符创 41 /// </summary> 42 public static string CookiesString 43 { 44 get; 45 set; 46 } 47 #endregion 48 49 #region 方法 50 /// <summary> 51 /// 用户登陆指定的网站 52 /// </summary> 53 /// <param name="loginUrl"></param> 54 /// <param name="account"></param> 55 /// <param name="password"></param> 56 public static void PostLogin(string loginUrl, string account, string password) 57 { 58 HttpWebRequest request = null; 59 HttpWebResponse response = null; 60 try 61 { 62 string postdata = "email=" + account + "&password="+password+"&origURL=" + "http://www.renren.com/home" + "&domain=renren.com";//模拟请求数据,数据样式可以用FireBug插件得到。 63 // string LoginUrl = "http://www.renren.com/PLogin.do"; 64 request = (HttpWebRequest)WebRequest.Create(loginUrl);//实例化web访问类 65 request.Credentials = CredentialCache.DefaultCredentials; 66 request.Method = "POST";//数据提交方式为POST 67 request.ContentType = "application/x-www-form-urlencoded"; //模拟头 68 request.AllowAutoRedirect = false; // 不用需自动跳转 69 //必须设置CookieContainer存储请求返回的Cookies 70 if (CookieContainer != null) 71 { 72 request.CookieContainer = CookieContainer; 73 } 74 else 75 { 76 request.CookieContainer = new CookieContainer(); 77 CookieContainer = request.CookieContainer; 78 } 79 request.KeepAlive = true; 80 //提交请求 81 byte[] postdatabytes = Encoding.UTF8.GetBytes(postdata); 82 request.ContentLength = postdatabytes.Length; 83 Stream stream; 84 stream = request.GetRequestStream(); 85 //设置POST 数据 86 stream.Write(postdatabytes, 0, postdatabytes.Length); 87 stream.Close(); 88 //接收响应 89 response = (HttpWebResponse)request.GetResponse(); 90 //保存返回cookie 91 response.Cookies = request.CookieContainer.GetCookies(request.RequestUri); 92 CookieCollection cook = response.Cookies; 93 string strcrook = request.CookieContainer.GetCookieHeader(request.RequestUri); 94 CookiesString = strcrook; 95 //取下一次GET跳转地址 96 StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8); 97 string content = sr.ReadToEnd(); 98 sr.Close(); 99 request.Abort(); 100 response.Close(); 101 //依据登陆成功后返回的Page信息,求出下次请求的url 102 //每个网站登陆后加载的Url和顺序不尽相同,以下两步需根据实际情况做特殊处理,从而得到下次请求的URL 103 string[] substr = content.Split(new char[] { '"' }); 104 NextRequestUrl = substr[1]; 105 } 106 catch (WebException ex) 107 { 108 MessageBox.Show(string.Format("登陆时出错,详细信息:{0}", ex.Message)); 109 } 110 } 111 /// <summary> 112 /// 获取用户登陆后下一次请求返回的内容 113 /// </summary> 114 public static void GetPage() 115 { 116 HttpWebRequest request = null; 117 HttpWebResponse response = null; 118 try 119 { 120 request = (HttpWebRequest)WebRequest.Create(NextRequestUrl); 121 request.Credentials = CredentialCache.DefaultCredentials; 122 request.Method = "GET"; 123 request.KeepAlive = true; 124 request.Headers.Add("Cookie:" + CookiesString); 125 request.CookieContainer = CookieContainer; 126 request.AllowAutoRedirect = false; 127 response = (HttpWebResponse)request.GetResponse(); 128 //设置cookie 129 CookiesString = request.CookieContainer.GetCookieHeader(request.RequestUri); 130 //取再次跳转链接 131 StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8); 132 string ss = sr.ReadToEnd(); 133 sr.Close(); 134 request.Abort(); 135 response.Close(); 136 //依据登陆成功后返回的Page信息,求出下次请求的url 137 //每个网站登陆后加载的Url和顺序不尽相同,以下两步需根据实际情况做特殊处理,从而得到下次请求的URL 138 string[] substr = ss.Split(new char[] { '"' }); 139 NextRequestUrl = substr[1]; 140 ResultHtml = ss; 141 } 142 catch (WebException ex) 143 { 144 MessageBox.Show(string.Format("获取页面HTML信息出错,详细信息:{0}",ex.Message)); 145 } 146 } 147 #endregion 148 149 } 150 }
以下是测试代码,POST请求一次,GET请求三次。最后得到登陆后加载的首页的HTML代码。当然,登陆后就可以依据当前的Cookie数据获取网站的其他子页面HTML。以下是登陆后加载的首页的HTML代码的逻辑。
View Code
1 private void Form1_Load(object sender, EventArgs e) 2 { 3 WebAutoLogin.PostLogin("http://www.renren.com/PLogin.do", "niuwenwen668@sina.com", "xxxxxxx"); 4 WebAutoLogin.GetPage(); 5 WebAutoLogin.GetPage(); 6 WebAutoLogin.GetPage(); 7 webBrowser1.DocumentText = WebAutoLogin.ResultHtml; 8 }
第一次POST数据的URL为登陆提交数据的页面,此地址不一定能在抓包工具中得到,这就需要分析,方法很多(网上很多),例如查看登陆页面源码等。
POST提交的数据可以在抓包工具中得到,以下是FireBug中得到的信息:
把代码Copy执行以下,自动登录成功了吧!!
好了,就这些了,此过程中就是每次请求都延续应用前一次请求返回的Cookie数据,只要这步原理理解,此过程也就没有什么难度了。