C#使用Socket登陆WordPress源码
就在昨晚,在本屌丝刚刚发布屌丝与女神的回忆史《C#外挂QQ找茬辅助源码,早期开发》后,在苏飞大哥的技术讨论群有个群友提出一个问题。使用http协议模拟工具可以登录成功Wordpress但是自己写代码死活登陆不上。本人玩Wordpress已经很多年了,在很多年前还没有女神的时候就开始有开发Wordpress客户端的冲动。最终都不了了之。今天群友提出的问题让我重拾以前的那份冲动….说多了,言归正传
本屌最开始也是使用苏飞大哥写的Httphelper类。也是死活登陆不上,取不到登陆之后的Cookie值。最后就在想,为什么Fiddler里面看到的报文跟我发过去的都差不多而不行呢。可能是在访问的时候某些参数不正确吧,那我把发送过去的报文做成一模一样的应该没有问题吧。所以下面用到了Socket访问80端口的形式发送报文..(下载地址在最后)
使用Socket方式发送报文以及提取Cookie并访问网站的代码:
1 class loginwp 2 { 3 public string PostData(string postURL, string postString, string encoding) 4 { 5 string strHTML = "";//用来保存获得的HTML代码 6 Uri URI = new Uri(postURL); 7 string sendString; 8 sendString = "POST {0} HTTP/1.1\r\n"; 9 sendString += "Host: {1}\r\n"; 10 sendString += "User-Agent:Mozilla/5.0 (Windows NT 6.1; rv:5.0) Gecko/20100101 Firefox/5.0\r\n"; 11 sendString += "Content-Type:application/x-www-form-urlencoded\r\n"; 12 sendString += "Content-Length:{2}\r\n"; 13 sendString += "Connection:close\r\n"; 14 sendString += "Cookie:wordpress_test_cookie=WP+Cookie+check\r\n\r\n"; 15 sendString += "{3}\r\n"; 16 sendString = string.Format(sendString, URI.PathAndQuery, URI.Host, postString.Length, postString); 17 Byte[] ByteGet = Encoding.GetEncoding(encoding).GetBytes(sendString); 18 IPAddress hostadd = Dns.GetHostEntry(URI.Host).AddressList[0]; 19 IPEndPoint EPhost = new IPEndPoint(hostadd, 80); 20 Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 21 s.Connect(EPhost); 22 if (!s.Connected) 23 { 24 strHTML = "链接主机失败"; 25 } 26 s.Send(ByteGet, ByteGet.Length, SocketFlags.None); 27 strHTML = Recv(s, Encoding.GetEncoding(encoding)); 28 return strHTML; 29 } 30 31 public static String Recv(Socket sock, Encoding encode) 32 { 33 Byte[] buffer = new Byte[1024]; 34 StringBuilder sb = new StringBuilder(); 35 36 Thread.Sleep(50);//根据页面响应时间进行微调 37 Int32 len = sock.Receive(buffer); 38 sb.Append(encode.GetString(buffer, 0, len)); 39 40 while (sock.Available > 0) 41 { 42 Thread.Sleep(300);//也可以视情况微调 43 Array.Clear(buffer, 0, buffer.Length); 44 len = sock.Receive(buffer); 45 sb.Append(encode.GetString(buffer, 0, len)); 46 string ss = encode.GetString(buffer, 0, len); 47 } 48 sock.Close(); 49 return sb.ToString(); 50 } 51 52 /// <summary> 53 /// 从返回的源代码中提取cookies 以及301或302跳转 54 /// </summary> 55 /// <param name="s"></param> 56 /// <param name="location"></param> 57 /// <returns></returns> 58 public string GetCookies(string html, out string location) 59 { 60 StringBuilder sbCookies = new StringBuilder(); 61 location = string.Empty; 62 string[] arr = html.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries); 63 foreach (string str in arr) 64 { 65 if (str.StartsWith("Set-Cookie: ")) 66 { 67 int intStart = str.IndexOf(";"); 68 string strCookie = str.Substring(12, intStart - 11); 69 sbCookies.Append(strCookie); 70 } 71 if (str.StartsWith("Location:")) 72 { 73 location = str.Substring(10); 74 } 75 } 76 return sbCookies.ToString(); 77 } 78 79 /// <summary> 80 /// 带上cookies 获取需要登录验证的页面 81 /// </summary> 82 /// <param name="url">请求的URL</param> 83 /// <param name="cookies">cookies字符串</param> 84 /// <param name="encoding">页面编码</param> 85 /// <returns></returns> 86 public string GetPage(string url, string cookies, string encoding) 87 { 88 Uri URI = new Uri(url); 89 string strHTML = string.Empty;//用来保存获得的HTML代码 90 IPHostEntry gist = Dns.GetHostEntry(URI.Host);//获得当前url的ip地址 91 IPAddress ip = gist.AddressList[0];//提取IP地址 92 IPEndPoint ipEnd = new IPEndPoint(ip, 80);//封装IP地址和端口 93 Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//实例化Stock 94 try 95 { 96 socket.Connect(ipEnd); 97 }//自动循环捕捉连接 98 catch 99 { } 100 string sendString = "GET " + URI.PathAndQuery + " HTTP/1.1\r\n"; 101 sendString += "Connection:close\r\n"; 102 sendString += "Content-Type: application/x-www-form-urlencoded\r\n"; 103 sendString += "Host:" + URI.Host + "\r\n"; 104 if (!string.IsNullOrEmpty(cookies)) 105 sendString += "Cookie:" + cookies + "\r\n\r\n"; 106 byte[] ms = UTF8Encoding.GetEncoding(encoding).GetBytes(sendString);//将头部转换成byte形式 107 socket.Send(ms);//发送 108 int recv = -1;//定义接受数据长度 109 byte[] data = new byte[1024];//用来保存接收数据 110 do 111 { 112 recv = socket.Receive(data); 113 strHTML += Encoding.GetEncoding(encoding).GetString(data, 0, recv); 114 } while (recv != 0); 115 return strHTML; 116 } 117 }
最后放上Demo:C#使用Socket登陆Wordpress.zip
本文来自放肆雷特 | 胖子的技术博客 欢迎关注胖子的新浪博客@大胖子蜀黍