首先獲取Token,根據Token獲取PubliKey,使用RSA加密POST數據html
private Regex _regex = new Regex(@"\{.*\}", RegexOptions.IgnoreCase); static void Main(string[] args) { new Program().Login("用戶名", "密碼"); Console.ReadLine(); } public static string Get_time_13() { DateTime d = DateTime.Now.AddHours(-8.0); DateTime d2 = Convert.ToDateTime("1970-01-01 "); return (d - d2).TotalMilliseconds.ToString("0"); } public void Login(string username, string pwd) { var cookieContainer = new CookieContainer(); var token = GetToken(cookieContainer); if (_regex.IsMatch(token)) { token = _regex.Match(token).Value; } var resultToken = JsonConvert.DeserializeObject<ResultToken>(token); var pubKey = GetPubKey(resultToken.Data.Token, cookieContainer); if (_regex.IsMatch(pubKey)) { pubKey = _regex.Match(pubKey).Value; } var publicKey = JsonConvert.DeserializeObject<PublicRsaKey>(pubKey); var rsakey = publicKey.Key; var pemToXml = RSAHelper.PemToXml(publicKey.Pubkey); var password = RSAHelper.RSAEncrypt(pemToXml, pwd); var url = "https://passport.baidu.com/v2/api/?login"; var postdata = string.Format("staticpage=http%3A%2F%2Fapp.baidu.com%2Fsfile%2Fv3Jump.html&charset=UTF-8&token={0}&tpl=wise&subpro=&apiver=v3&tt={1}&codestring=&safeflg=0&u=%0D%0A%0D%0Ahttp%3A%2F%2Fapp.baidu.com%2Findex%3Fregdev%3D1&isPhone=false&quick_user=0&logintype=dialogLogin&logLoginType=pc_loginDialog&idc=&loginmerge=true&splogin=newuser&username={2}&password={3}&verifycode=&mem_pass=on&rsakey={4}&crypttype=12&ppui_logintime=426406&callback=parent.bd__pcbs__mwrr8d", resultToken.Data.Token, GetJsTimeSeconds(), HttpUtility.UrlEncode(username), HttpUtility.UrlEncode(password), HttpUtility.UrlEncode(rsakey)); PostRequest(url, cookieContainer, postdata); } private string GetToken(CookieContainer cookieContainer) { var url = string.Format(@"https://passport.baidu.com/v2/api/?getapi&tpl=wise&apiver=v3&tt={0}&class=login&logintype=dialogLogin&callback=bd__cbs__v5pvt1", GetJsTimeSeconds()); GetHtml(url, ref cookieContainer); return GetHtml(url, ref cookieContainer); } private string GetPubKey(string token, CookieContainer cookieContainer) { var url = string.Format("https://passport.baidu.com/v2/getpublickey?token={0}&tpl=wise&apiver=v3&tt={1}&callback=bd__cbs__fwnq4r", token, GetJsTimeSeconds()); var html = GetHtml(url, ref cookieContainer); return html; } private static string GetJsTimeSeconds() { return (DateTime.UtcNow - DateTime.Parse("1970-01-01 0:0:0")).TotalMilliseconds.ToString("0"); } private string GetHtml(string url, ref CookieContainer cookie) { HttpWebRequest request = null; HttpWebResponse response = null; try { request = (HttpWebRequest)WebRequest.Create(url); request.Proxy = null; request.Credentials = CredentialCache.DefaultCredentials; request.Method = "GET"; request.KeepAlive = true; request.Accept = "application/json, text/plain, */*"; request.CookieContainer = cookie; request.AllowAutoRedirect = true; response = (HttpWebResponse)request.GetResponse(); var sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8); string ss = sr.ReadToEnd(); sr.Close(); request.Abort(); response.Close(); return ss; } catch (WebException ex) { return ""; } } public void PostRequest(string url, CookieContainer cookieContainer, string postData) { HttpWebRequest request = null; HttpWebResponse response = null; try { request = (HttpWebRequest)WebRequest.Create(url);//實例化web訪問類 request.UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36"; request.Credentials = CredentialCache.DefaultCredentials; request.Method = "POST"; //數據提交方式爲POST request.ContentType = "application/x-www-form-urlencoded"; request.AllowAutoRedirect = false; // 不用需自動跳轉 request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8"; request.CookieContainer = cookieContainer; request.KeepAlive = true; //提交請求 byte[] postdatabytes = Encoding.UTF8.GetBytes(postData); request.ContentLength = postdatabytes.Length; Stream stream; stream = request.GetRequestStream(); //設置POST 數據 stream.Write(postdatabytes, 0, postdatabytes.Length); stream.Close(); //接收響應 response = (HttpWebResponse)request.GetResponse(); var cookieCollection = response.Cookies;//拿到bduss 說明登陸成功 //保存返回cookie //取下一次GET跳轉地址 StreamReader sr = new StreamReader(response.GetResponseStream(), Encoding.UTF8); string content = sr.ReadToEnd(); CheckLogin(content); CheckSendMSG(cookieContainer); sr.Close(); } catch (Exception ex) { } finally { if (request != null) request.Abort(); if (response != null) response.Close(); } } public static void CheckLogin(string content) { int after = content.IndexOf("err_no"); if (after > 0) { string html = content.Substring(after); int index = html.IndexOf("="); int and = html.IndexOf("&"); string ErrorCode = html.Substring(index + 1, and - index - 1); switch (ErrorCode) { case "0": Console.WriteLine("登陸成功"); break; case "7": Console.WriteLine("密碼錯誤"); break; case "257": Console.WriteLine("用戶名不存在"); break; } } }
向指定收件人發送百度私信:web
public static string FindString(string content, string str)//找到字符串位置 { int num = content.IndexOf(str); if (num >= 0) { int length = str.Length; return content.Substring(num + length, content.Length - num - length); } return ""; } public static string GetString(string content, string str)//截取字符串 { int One = content.IndexOf(str); int Two = content.IndexOf(str, One + 1); return content.Substring(One + 1, Two - One - 1); } /// <summary> /// 發送百度私信 /// </summary> /// <param name="User">收件人</param> /// <param name="MSG">發送的內容</param> /// <param name="cookie">Cookie</param> /// <param name="Token">Token字符串</param> /// <param name="Vcode">驗證碼</param> /// <param name="VcodeStr">動態驗證碼字符串</param> /// <returns></returns> public string SendMSG(string User, string MSG, CookieContainer cookie, string Token, string Vcode, string VcodeStr) { HttpHelper http = new HttpHelper(cookie); http.Encoding = Encoding.UTF8; string html = http.GetHtml("http://msg.baidu.com/msg/writing/submit/msg", cookie, "msgcontent=" + MSG + "&vcode=" + Vcode + "&msgvcode=" + VcodeStr + "&msgreceiver=" + HttpUtility.UrlEncode(User, Encoding.UTF8) + ";&bdstoken=" + Token + "&qing_request_source=", true); //string html = http.GetHtml("http://msg.baidu.com/msg/home"); return html; } public void CheckSendMSG(CookieContainer cookie) { try { //獲取Token string TokenHtml = GetHtml("http://msg.baidu.com/msg/writing", ref cookie); string Token = GetString(FindString(TokenHtml, "window.msgBdsToken"), "\""); //獲取驗證碼字符串 string VcodeHtml = GetHtml("https://passport.baidu.com/v2/?reggetcodestr&tpl=qing&app=stelyg&apiver=v3&class=reg&echoback=msg.home.editor.changeVerifyCode&tt=1471663009977&callback=msg.msgpublish.Form.changeVerifyCode", ref cookie); string VcodeStr = GetString(FindString(VcodeHtml, "\"verifyStr\""), "\""); //獲取驗證碼圖片 WebClient client = new WebClient(); client.DownloadFile("https://passport.baidu.com/cgi-bin/genimage?" + VcodeStr + "&t=1471585459062", "D:\\驗證碼.png"); Console.Write("請輸入收件人:"); string User = Console.ReadLine(); Console.Write("請輸入發送內容:"); string MSG = Console.ReadLine(); Console.Write("請輸入驗證碼:"); string Vcode = Console.ReadLine(); string html = SendMSG(User, MSG, cookie, Token, Vcode, VcodeStr); string ErrorCode = GetString(FindString(html, "errorNo"), "\""); switch (ErrorCode) { case "0": Console.WriteLine("發送成功"); break; case "3018": Console.WriteLine("用戶名不存在"); break; case "3014": Console.WriteLine("驗證碼錯誤"); break; } Console.WriteLine(html); } catch (Exception e) { } }
對RAS祕鑰的加密和解密方法,須要引用BouncyCastle.Crypto.dlljson
public static string PemToXml(string pem) { if (pem.StartsWith("-----BEGIN RSA PRIVATE KEY-----") || pem.StartsWith("-----BEGIN PRIVATE KEY-----")) { return GetXmlRsaKey(pem, obj => { if ((obj as RsaPrivateCrtKeyParameters) != null) return DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)obj); var keyPair = (AsymmetricCipherKeyPair)obj; return DotNetUtilities.ToRSA((RsaPrivateCrtKeyParameters)keyPair.Private); }, rsa => rsa.ToXmlString(true)); } if (pem.StartsWith("-----BEGIN PUBLIC KEY-----")) { return GetXmlRsaKey(pem, obj => { var publicKey = (RsaKeyParameters)obj; return DotNetUtilities.ToRSA(publicKey); }, rsa => rsa.ToXmlString(false)); } throw new InvalidKeyException("Unsupported PEM format..."); } private static string GetXmlRsaKey(string pem, Func<object, RSA> getRsa, Func<RSA, string> getKey) { using (var ms = new MemoryStream()) using (var sw = new StreamWriter(ms)) using (var sr = new StreamReader(ms)) { sw.Write(pem); sw.Flush(); ms.Position = 0; var pr = new PemReader(sr); object keyPair = pr.ReadObject(); using (RSA rsa = getRsa(keyPair)) { var xml = getKey(rsa); return xml; } } } /// <summary> /// RSA加密 /// </summary> /// <param name="publickey"></param> /// <param name="content"></param> /// <returns></returns> public static string RSAEncrypt(string publickey, string content) { RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); byte[] cipherbytes; rsa.FromXmlString(publickey); cipherbytes = rsa.Encrypt(Encoding.UTF8.GetBytes(content), false); return Convert.ToBase64String(cipherbytes); } /// <summary> /// RSA解密 /// </summary> /// <param name="privatekey"></param> /// <param name="content"></param> /// <returns></returns> public static string RSADecrypt(string privatekey, string content) { privatekey = @"<RSAKeyValue><Modulus>5m9m14XH3oqLJ8bNGw9e4rGpXpcktv9MSkHSVFVMjHbfv+SJ5v0ubqQxa5YjLN4vc49z7SVju8s0X4gZ6AzZTn06jzWOgyPRV54Q4I0DCYadWW4Ze3e+BOtwgVU1Og3qHKn8vygoj40J6U85Z/PTJu3hN1m75Zr195ju7g9v4Hk=</Modulus><Exponent>AQAB</Exponent><P>/hf2dnK7rNfl3lbqghWcpFdu778hUpIEBixCDL5WiBtpkZdpSw90aERmHJYaW2RGvGRi6zSftLh00KHsPcNUMw==</P><Q>6Cn/jOLrPapDTEp1Fkq+uz++1Do0eeX7HYqi9rY29CqShzCeI7LEYOoSwYuAJ3xA/DuCdQENPSoJ9KFbO4Wsow==</Q><DP>ga1rHIJro8e/yhxjrKYo/nqc5ICQGhrpMNlPkD9n3CjZVPOISkWF7FzUHEzDANeJfkZhcZa21z24aG3rKo5Qnw==</DP><DQ>MNGsCB8rYlMsRZ2ek2pyQwO7h/sZT8y5ilO9wu08Dwnot/7UMiOEQfDWstY3w5XQQHnvC9WFyCfP4h4QBissyw==</DQ><InverseQ>EG02S7SADhH1EVT9DD0Z62Y0uY7gIYvxX/uq+IzKSCwB8M2G7Qv9xgZQaQlLpCaeKbux3Y59hHM+KpamGL19Kg==</InverseQ><D>vmaYHEbPAgOJvaEXQl+t8DQKFT1fudEysTy31LTyXjGu6XiltXXHUuZaa2IPyHgBz0Nd7znwsW/S44iql0Fen1kzKioEL3svANui63O3o5xdDeExVM6zOf1wUUh/oldovPweChyoAdMtUzgvCbJk1sYDJf++Nr0FeNW1RB1XG30=</D></RSAKeyValue>"; RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); byte[] cipherbytes; rsa.FromXmlString(privatekey); cipherbytes = rsa.Decrypt(Convert.FromBase64String(content), false); return Encoding.UTF8.GetString(cipherbytes); }
封裝字段:api
public class PublicRsaKey { [JsonProperty("errno")] public string Errno { get; set; } [JsonProperty("msg")] public string Msg { get; set; } [JsonProperty("pubkey")] public string Pubkey { get; set; } [JsonProperty("key")] public string Key { get; set; } } public class ErrInfo { [JsonProperty("no")] public string No { get; set; } } public class Loginrecord { [JsonProperty("email")] public object[] Email { get; set; } [JsonProperty("phone")] public object[] Phone { get; set; } } public class Data { [JsonProperty("rememberedUserName")] public string RememberedUserName { get; set; } [JsonProperty("codeString")] public string CodeString { get; set; } [JsonProperty("token")] public string Token { get; set; } [JsonProperty("cookie")] public string Cookie { get; set; } [JsonProperty("usernametype")] public string Usernametype { get; set; } [JsonProperty("spLogin")] public string SpLogin { get; set; } [JsonProperty("disable")] public string Disable { get; set; } [JsonProperty("loginrecord")] public Loginrecord Loginrecord { get; set; } } public class ResultToken { [JsonProperty("errInfo")] public ErrInfo ErrInfo { get; set; } [JsonProperty("data")] public Data Data { get; set; } }