经过两天的努力 已经成功将QQ登录集成到了 城记网 上。感谢腾讯提供的帮助文档,和关键时刻给的技术支持。我的网站是asp.net写的,有需要的网友可以联系我。 呵呵。(尽管是垃圾站,只要你愿意,又有什么关系呢?)
QQ Oauth 只提供PHP的接入demo ,针对 ASP.net 的只有一个网友开发的SDK包,下载地址还老打不开,后来我从CSDN上下载了一个,看了以后感觉太复杂了,我个人感觉做这么个小事情不需要搞个SDK出来,不如自己按帮助文档去写,这样自己写的方法灵活性就高一些,于是就按文档学习开发。其实文档写得很清晰,耐心一看就明白了。
不讲太多的郁闷的过程了,直接说解决办法。
办这个事情主要要知道下面几个事情。
两个重点(如下):
第一个重点:请求Token的步骤,
1:请求未授权的临时token。请求成功以后会转到QQ登录页面。
2:请求已授权的临时token。登陆成功以后获得。
3:请求已授权的Access token。
第二个重点:签名的算法。
签名的值计算有一个指定的规则,请参考腾讯开放社区帮助文档,这是最 好的资料。
注意点:
没有申请APPID和APPKEY的先去申请。
传递的每一参数都要URLENcode,注意是每一个,包括动态生成的签名。
参数之间是有顺序的,是升序排列的,无论有多少个,都要排序。
各个步骤之间是有关联的,下一步的提交往往需要上一步的返回参数。
我采取的文档结构:
总共三个文件 ,非常简单。
一个放在APPcode下面的类。用来发送请求和接待参数。
两个前台页面,主要是对类的调用。
下面把类的代码完全贴出,你知要一看见类,就知道怎么写前台页面了,很简单。
using System; using System.Data; using System.Configuration; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Web.UI.HtmlControls; using System.Text; using System.Net; using System.Security.Cryptography; using System.IO; using System.Collections; /// <summary> /// QQOAuth 的摘要说明 /// 版权:城记网(114box.com),请保留版权 /// 作者:JXY /// Q Q:281773404 /// 日 期:2011-08-20 /// </summary> public class QQOAuth { public static string appid = "21****"; public static string appkey = "427ca17***************************de"; public static string questadd = "http://openapi.qzone.qq.com/oauth/qzoneoauth_request_token"; /// <summary> /// 请求临时的Token /// </summary> /// <returns></returns> public static string GetTempToken() { string myrandomnum = oauthnonce(); //随机数 string unixtime = GenerateTimeStamp();//时间戳 string token_parameter = "oauth_consumer_key=" + appid + "&oauth_nonce=" + myrandomnum + "&oauth_signature_method=HMAC-SHA1&oauth_timestamp=" + unixtime + "&oauth_version=1.0"; string code_token_parameter = "GET&" + Uri.EscapeDataString(questadd) + "&" + Uri.EscapeDataString(token_parameter); string miyuetemp = appkey + "&"; string signvl = ToBase64hmac(code_token_parameter, miyuetemp); string url = string.Format("{0}?{1}{2}{3}",questadd, token_parameter, "&oauth_signature=", Uri.EscapeDataString(signvl)); string QQreturnstr = RequestUrl(url); return QQreturnstr; } /// <summary> /// 请求ACCESS的Token /// </summary> /// <param name="oauth_token">获得授权临时Token的时候获得的参数</param> /// <param name="oauth_vericode">获得授权临时Token的时候获得的验证代码</param> /// <param name="oauth_token_secret">获得授权临时Token的时候获得的密钥</param> /// <returns>返回ACCess Token</returns> public static string GetAccessToken(string oauth_token, string oauth_vericode, string oauth_token_secret) { string thisquestadd = "http://openapi.qzone.qq.com/oauth/qzoneoauth_access_token"; string myrandomnum = oauthnonce(); //随机数 string unixtime = GenerateTimeStamp();//时间戳 string token_parameter = "oauth_consumer_key=" + appid + "&oauth_nonce=" + myrandomnum + "&oauth_signature_method=HMAC-SHA1&oauth_timestamp=" + unixtime + "&oauth_token=" + oauth_token + "&oauth_vericode=" + oauth_vericode + "&oauth_version=1.0"; string code_token_parameter = "GET&" + Uri.EscapeDataString(thisquestadd) + "&" + Uri.EscapeDataString(token_parameter); string miyuetemp = appkey + "&" + oauth_token_secret; string signvl = ToBase64hmac(code_token_parameter, miyuetemp); string url = string.Format("{0}?{1}{2}{3}",thisquestadd, token_parameter, "&oauth_signature=", Uri.EscapeDataString(signvl)); string QQreturnstr = RequestUrl(url); return QQreturnstr; } /// <summary> /// 获得用户信息的API /// </summary> /// <param name="oauth_token">Access token 请求是返回的</param> /// <param name="openid">Access token 请求是返回的 openid</param> /// <param name="oauth_token_secret">Access token 请求是返回的动态密钥</param> /// <returns>XML</returns> public static string GetQQUserInfo(string oauth_token, string openid, string oauth_token_secret) { string thisquestadd = "http://openapi.qzone.qq.com/user/get_user_info"; string myrandomnum = oauthnonce(); //随机数 string unixtime = GenerateTimeStamp();//时间戳 string token_parameter = "format=xml&oauth_consumer_key=" + appid + "&oauth_nonce=" + myrandomnum + "&oauth_signature_method=HMAC-SHA1&oauth_timestamp=" + unixtime + "&oauth_token=" + oauth_token + "&oauth_version=1.0&openid="+openid; string code_token_parameter = "GET&" + Uri.EscapeDataString(thisquestadd) + "&" + Uri.EscapeDataString(token_parameter); string miyuetemp = appkey + "&" + oauth_token_secret; string signvl = ToBase64hmac(code_token_parameter, miyuetemp); string url = string.Format("{0}?{1}{2}{3}", thisquestadd, token_parameter, "&oauth_signature=", Uri.EscapeDataString(signvl)); string QQreturnstr = RequestUrl(url); return QQreturnstr; } #region 服务方法 /// <summary> /// hmacSha1算法加密并返回ToBase64String /// </summary> /// <param name="strText">签名参数字符串</param> /// <param name="strKey">密钥</param> /// <returns>返回一个签名参数值</returns> public static string ToBase64hmac(string strText, string strKey) { HMACSHA1 myHMACSHA1 = new HMACSHA1(Encoding.UTF8.GetBytes(strKey)); byte[] byteText = myHMACSHA1.ComputeHash(Encoding.UTF8.GetBytes(strText)); return System.Convert.ToBase64String(byteText); } /// <summary> /// 请求指定url地址并返回结果 /// </summary> /// <param name="url"></param> /// <returns></returns> public static string RequestUrl(string url) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url); request.Method = "GET"; request.MaximumAutomaticRedirections = 3; request.Timeout = 0x2710; Stream responseStream = ((HttpWebResponse)request.GetResponse()).GetResponseStream(); StreamReader reader = new StreamReader(responseStream); string str = reader.ReadToEnd(); reader.Close(); responseStream.Close(); return str; } /// <summary> /// Base64编码,此方法的功能同方法ToBase64hmac /// 目前内有使用该方法 /// </summary> /// <returns></returns> public static string HMACSHA1(string consumer_secret, string oauth_token_secret, string signaturebasestring) { HMACSHA1 hmacsha1 = new HMACSHA1(); hmacsha1.Key = Encoding.ASCII.GetBytes(consumer_secret + "&" + oauth_token_secret); byte[] dataBuffer = System.Text.Encoding.ASCII.GetBytes(signaturebasestring); byte[] hashBytes = hmacsha1.ComputeHash(dataBuffer); string signature = Convert.ToBase64String(hashBytes); return signature; } /// <summary> /// 时间戳返回unix时间戳 /// </summary> /// <returns></returns> public static string GenerateTimeStamp() { TimeSpan ts = DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0); return Convert.ToInt64(ts.TotalSeconds).ToString(); } /// <summary> /// 随机字符串 /// </summary> /// <returns></returns> public static string oauthnonce() { int number; string checkCode = String.Empty; Random random = new Random(); for (int i = 0; i < 9; i++) { number = random.Next(0, 9); checkCode += number.ToString(); } return checkCode; } /// <summary> /// 将认证获得的参数简单转化为哈希表 /// </summary> /// <param name="varstr">获得参数的字符串</param> /// <returns></returns> public static Hashtable Str2Hash(string varstr) { Hashtable myhash = new Hashtable(); if (varstr.Trim() != string.Empty) { string[] temparr = varstr.Split('&'); foreach (string onevarstr in temparr) { string[] onevararr=onevarstr.Split('='); myhash.Add(onevararr[0], onevararr[1]); } return myhash; } else { return null; } } #endregion }
将上面的代码放到APPcode 下面,按步骤写你的前台页面就行了。
我也做过PHP开发,我个人认为asp.net做这个要比PHP简单明了,不知道为什么腾讯不给出asp.net方面的demo。难道是对微软的歧视?!呵呵。
demo 下载(我要了5分,主要是我看了两天的文档写成的)