首先列举比较重要的问题在前面。
1.关于QQ密码码的加密:
2.关于登陆是否需要验证码的校验。
3. 发日志的时候g_tk参数的算法。
?
分析过程。
1.登陆的时候,需要先判断是否需要使用验证码。
string url = String.Format("http://ptlogin2.qq.com/check?uin={0}&appid={1}&r=0.{2}", TxtUser.Text.Trim(), "2001601", Bases.GetGuid(Bases.RandEnum.Numeric, 16));
进行Get请示,如果返回值 是1开头结果的需要验证码,如果是0开头的,是不需要验证码的。
?
2.有验证码的情况 ,获得验证码图片地址,同时要记录验证码的cookie,在提交的时候需要用到。
string strImageUrl = String.Format("http://captcha.qq.com/getimage?&uin={0}&vc_type={1}&aid={2}&0.{3}",TxtUser.Text.Trim(),vcCode, "2001601", Bases.GetGuid(Bases.RandEnum.Numeric, 16));
?
3.进行登陆,
登陆地址:http://ptlogin2.qq.com/login?u={0}&p={1}&verifycode={2}&aid=1006102&u1=http%3A%2F%2Fid.qq.com%2Findex.html&h=1&ptredirect=1&ptlang=2052&from_ui=1&dumy=&fp=loginerroralert
注:u:你的QQ号, p:加密过的QQ密码,verifycode:验证码
?
??? 3.1 :QQ密码的加密代码:c#版的。
public static class qqPwdEncrypt
?? {
?????? /// <summary>
?????? /// 计算网页上QQ登录时密码加密后的结果
?????? /// </summary>
?????? /// <param name="pwd" />QQ密码</param>
?????? /// <param name="verifyCode" />验证码</param>
?????? /// <returns></returns>
?????? public static String Encrypt(string pwd, string verifyCode)
?????? {
?????????? return (md5(md5_3(pwd).ToUpper() + verifyCode.ToUpper())).ToUpper();
?????? }
?????? /// <summary>
?????? /// 计算字符串的三次MD5
?????? /// </summary>
?????? /// <param name="s" /></param>
?????? /// <returns></returns>
?????? private static String md5_3(String s)
?????? {
?????????? System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
?????????? byte[] bytes = System.Text.Encoding.UTF8.GetBytes(s);
?????????? bytes = md5.ComputeHash(bytes);
?????????? bytes = md5.ComputeHash(bytes);
?????????? bytes = md5.ComputeHash(bytes);
?????????? md5.Clear();
?????????? string ret = "";
?????????? for (int i = 0; i < bytes.Length; i++)
?????????? {
?????????????? ret += Convert.ToString(bytes[i], 16).PadLeft(2, '0');
?????????? }
?????????? return ret.PadLeft(32, '0');
?????? }
?????? /// <summary>
?????? /// 计算字符串的一次MD5
?????? /// </summary>
?????? /// <param name="s" /></param>
?????? /// <returns></returns>
?????? private static String md5(String s)
?????? {
?????????? System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
?????????? byte[] bytes = System.Text.Encoding.UTF8.GetBytes(s);
?????????? bytes = md5.ComputeHash(bytes);
?????????? md5.Clear();
?????????? string ret = "";
?????????? for (int i = 0; i < bytes.Length; i++)
?????????? {
?????????????? ret += Convert.ToString(bytes[i], 16).PadLeft(2, '0');
?????????? }
?????????? return ret.PadLeft(32, '0');
?????? }
?? }
3.2 关于js版的加密方法,请直接查看源代码,从QQ的页面上读取。
?
4.登陆成功后,开始发日志,
发日志地址:http://b.qzone.qq.com/cgi-bin/blognew/blog_add?g_tk=" + gtkValue
1:g_tk的参数如何取:
???? gtkValue的值是也是经过QQ加密过的
??? 加密原理:对于登陆成功后,会在登陆成功的cookie值中有一个skey的cookie,取该cookie的值,进行循环取单字符的二进制并取左值。
?? 找了一个获得gtkValue的js方法:【期待谁可以翻译成c#版的,因为js的方法,在c#的调用不太方便,还要引用一个dll的控件才可以。】
js方法提供如下:
function getGTK(str){
?? var hash = 5381;
?? for(var i = 0, len = str.length; i < len; ++i)
?? {
?? hash += (hash << 5) + str.charAt(i).charCodeAt();
?? }
?? return hash & 0x7fffffff;
}
通过调用些方法后,就可以获得发日志的具体地址了、
?
5.进行post提供要发的日志内容【注:登陆的时候,是get请求,非post请求】
前面都很顺利,到这里把我卡住了,不知道为什么提交后,没有数据返回,相对应也就是没有发布成功,也怪调试不细心。
后来发现提交的时候,会catch到 “关于“服务器提交了协议冲突. Section=ResponseStatusLine"
经常查询问题根源:【网上找的,嘿嘿】
The? server? committed? a? protocol? violation.? Section=ResponseHeader? Detail=CR? must? be? followed? by? LF 微软没有容忍不符合RFC? 822中的httpHeader必须以CRLF结束的规定的服务器响应。
通过修改配置文件解决:在app.config(WinForm)或web.config(Web)文件里修改。
WinForm下的app.config默认不存在,手动在Debug文件夹所在的同级目录下新建一个XML配置文件,内容为:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.net>
??????? <settings>
??????????? <httpWebRequest? useUnsafeHeaderParsing= "true "? />
??????? </settings>
??? </system.net>
</configuration>
编译以后会在Debug下面自动创建一个 程序名.exe.config 的配置文件
?
加入以上代码就OK了。
本文以记录分析过程,并留以后查看备忘 ,如果对大家无用,请飘了。哈
?
关于程序文章,或收藏一般同步发到javaeye,cnblogs,
关于其它文章,一般同步发到sina,QQ空间。
?
发成功了。哈哈。