QQ开放平台 OAUTH2.0 QqConnetSDK 登录,运行原理,附源码。
供大家研究使用,您可以对源代码进行修正编写。有很多不足,有很多缺点,在这里我只编写原理。
您需要开放式站点,做为了解它,您需要编写补充很多,或者您可以按照我的使用提供下载,进行编写其余内容补充及修正。谢谢大家,让大家的站点也融合这玩意。
开发环境:vs2005
QqConnetSDK
// 默认“Microsoft XML,v3.0”,其他版本也可以,只要能编译通过,步骤如下。
// 添加引用 -> “COM” 选项卡 -> 找到组件名称为“Microsoft XML,v3.0”
LoginToQQ.aspx 登录
QQCallback.aspx 回调访问页面
QqConnetSDK 项目sdk
QqConnet QqConnet基础类 ;您可以改进
ConfigurationHandler 配置节点句柄类 ;用于扩展配置文件节点,您可以改进
JSON JSON分析类 ;您可以改进
UserInfo 用户实体类 ;您可以改进,其他实体类不在一一列出,自行扩展。
web.config 站点配置文件
<add key="OAUTH_CONSUMER_KEY" value="10000000" /> 您的 app id
<add key="OAUTH_CONSUMER_SECRET" value="AbcdAbcdAbcdAbcdAbcdAbcdAbcdAbcd" /> 您的 app key
<add key="CALLBACK_URL" value="http://您的站点/QQCallback.aspx" /> 您的回调处理地址
QqConnetSDK
using System; using System.Data; using System.Configuration; using System.Text; using System.Web; using System.Web.UI.WebControls; using System.Collections.Generic; using System.Text.RegularExpressions; using System.Reflection; // 默认“Microsoft XML,v3.0”,其他版本也可以,只要能编译通过,步骤如下。 // 添加引用 -> “COM” 选项卡 -> 找到组件名称为“Microsoft XML,v3.0” using MSXML2; using System.Net; using System.Collections; using System.Xml; namespace QqConnetSDK { /// <summary> /// QqConnet 基础类 /// </summary> #region QqConnet public class QqConnet { private string QQ_OAUTH_CONSUMER_KEY; private string QQ_OAUTH_CONSUMER_SECRET; private string QQ_CALLBACK_URL; private string QQ_SCOPE; public string State = ""; public QqConnet() { Hashtable table = ConfigurationManager.GetSection("QzoneGroups/QzoneSection") as Hashtable; this.VerifyQzoneSection(table); this.QQ_OAUTH_CONSUMER_KEY = table["OAUTH_CONSUMER_KEY"].ToString();//APP ID this.QQ_OAUTH_CONSUMER_SECRET = table["OAUTH_CONSUMER_SECRET"].ToString();//APP KEY this.QQ_CALLBACK_URL = table["CALLBACK_URL"].ToString();//回调地址。 this.QQ_SCOPE = "get_user_info";//授权项 } /// <summary> /// 检测QzoneSection节点 /// </summary> /// <param name="table"></param> private void VerifyQzoneSection(Hashtable table) { if (table == null) this.ShowErrMsg("QzoneGroups/QzoneSection 不存在.", 0); if (table.Count <= 0) this.ShowErrMsg("QzoneGroups/QzoneSection 不存在.", 0); if (table["OAUTH_CONSUMER_KEY"] == null) this.ShowErrMsg("QzoneGroups/QzoneSection/OAUTH_CONSUMER_KEY 节点不存在.", 0); if (table["OAUTH_CONSUMER_SECRET"] == null) this.ShowErrMsg("QzoneGroups/QzoneSection/OAUTH_CONSUMER_SECRET 节点不存在.", 0); if (table["CALLBACK_URL"] == null) this.ShowErrMsg("QzoneGroups/QzoneSection/CALLBACK_URL 节点不存在.", 0); } public string APP_ID { get { return this.QQ_OAUTH_CONSUMER_KEY; } } /// <summary> /// State 数据. /// </summary> /// <returns></returns> private void GenerationState() { string value = Guid.NewGuid().ToString(); this.State = value.Replace("-", ""); } /// <summary> /// Get方法请求url,获取请求内容 /// </summary> /// <param name="Url"></param> /// <returns></returns> public string RequestUrl(string Url) { ServerXMLHTTP xmlhttp = new ServerXMLHTTP(); xmlhttp.setTimeouts(10000, 10000, 10000, 50000); xmlhttp.open("GET", Url, false, null, null); xmlhttp.send(""); if (xmlhttp.readyState == 4) { return xmlhttp.responseText; } return ""; } ///// <summary> ///// Post方法请求url,获取请求内容 ///// </summary> ///// <param name="Url"></param> ///// <param name="data"></param> ///// <returns></returns> //public string RequestUrl_post(string Url, string data) //{ // ServerXMLHTTP xmlhttp = new ServerXMLHTTP(); // xmlhttp.setTimeouts(10000, 10000, 10000, 50000); // xmlhttp.open("POST", Url, false, null, null); // xmlhttp.setRequestHeader("Host", " graph.qq.com"); // xmlhttp.setRequestHeader("content-length ", data.Length.ToString()); // xmlhttp.setRequestHeader("content-type ", "application/x-www-form-urlencoded"); // xmlhttp.setRequestHeader("Connection", " Keep-Alive"); // xmlhttp.setRequestHeader("Cache-Control", " no-cache"); // xmlhttp.send(data); // if (xmlhttp.readyState == 4) // { // return xmlhttp.responseText; // } // return ""; //} /// <summary> /// 生成登录地址 /// </summary> /// <returns></returns> public string GetAuthorization_Code() { this.GenerationState(); string url, str; url = "https://graph.qq.com/oauth2.0/authorize"; str = "client_id=" + this.QQ_OAUTH_CONSUMER_KEY; str += "&redirect_uri=" + this.QQ_CALLBACK_URL; str += "&response_type=code"; str += "&scope=" + this.QQ_SCOPE; str += "&state=" + this.State; url = url + "?" + str; return url; } /// <summary> /// 检测是否合法 /// </summary> /// <returns></returns> public bool VerifyCallback() { string Code = this.Request("code"); string State = this.Request("state"); if (Code != "") { return true; } return false; } /// <summary> /// 获取 access_token /// 示例.返回结果:正确 access_token=ABCDEFGABCDEFGABCDEFG&expires_in=7776000; /// </summary> /// <returns></returns> public string GetAccess_Token() { string url, str, result; url = "https://graph.qq.com/oauth2.0/token"; str = "client_id=" + this.QQ_OAUTH_CONSUMER_KEY; str += "&client_secret=" + this.QQ_OAUTH_CONSUMER_SECRET; str += "&redirect_uri=" + this.QQ_CALLBACK_URL; str += "&grant_type=authorization_code"; str += "&code=" + this.Request("code"); str += "&state=" + this.Request("state"); url = url + "?" + str; result = RequestUrl(url); this.ShowErrMsg(result); result = result.Split('&')[0]; result = result.Replace("access_token=", ""); return result; } /// <summary> /// 获取Openid /// 示例.返回结果:正确 callback( {"client_id":"100000001","openid":"ABCDEFGABCDEFGABCDEFG"} ); /// </summary> /// <returns></returns> public string GetOpenid(string Access_Token) { string url, str, result; url = "https://graph.qq.com/oauth2.0/me"; str = "access_token=" + Access_Token; url = url + "?" + str; result = RequestUrl(url); this.ShowErrMsg(result); JSON j = new JSON(result); return j.GetValue("openid").ToString(); } ///// <summary> ///// 发送记录到微博 ///// </summary> ///// <param name="content">发送内容</param> ///// <returns></returns> //public string Post_Webo(string Access_Token, string Openid, string content) //{ // string url, str; // url = "https://graph.qq.com/t/add_t"; // str = "oauth_consumer_key=" + this.QQ_OAUTH_CONSUMER_KEY; // str += "&access_token=" + Access_Token; // str += "&openid=" + Openid; // str += "&content=" + content; // return RequestUrl_post(url, str); //} /// <summary> /// 获取用户信息 /// </summary> /// <returns></returns> public UserInfo GetUserInfo(string Access_Token, string Openid) { string url, str, result; url = "https://graph.qq.com/user/get_user_info"; str = "oauth_consumer_key=" + this.QQ_OAUTH_CONSUMER_KEY; str += "&access_token=" + Access_Token; str += "&openid=" + Openid; url += "?" + str; result = RequestUrl(url); this.ShowErrMsg(result); JSON j = new JSON(result); UserInfo src = new UserInfo(); src = j.Convert<UserInfo>(src); return src; } /// <summary> /// 显示错误提示信息 /// </summary> /// <param name="error"></param> public void ShowErrMsg(string ErrMsg, params object[] ErrParams) { string error = ""; if (ErrParams.Length > 0) { error = ErrMsg; } else { int num = ErrMsg.IndexOf("\"error\""); if (num != -1) { JSON j = new JSON(ErrMsg); string description = j.GetValue("error_description").ToString(); switch (description) { case "code is reused error": //错误提示:code代码已被使用,无法重复使用该代码。其他错误不在一一列出。 break; } error = ErrMsg; } } if (error != "") { HttpContext.Current.Response.Write(ErrMsg); HttpContext.Current.Response.End(); } } /// <summary> /// 获取与设置服务端会话 /// </summary> /// <returns></returns> public object Session(string name, params object[] value) { object result = ""; if (value.Length > 0) HttpContext.Current.Session[name] = value[0]; else result = HttpContext.Current.Session[name]; return result == null ? "" : result; } /// <summary> /// 获取接收地址栏参数值 /// </summary> /// <param name="name"></param> /// <returns></returns> public string Request(string name) { string value = HttpContext.Current.Request.QueryString[name]; return value == null ? "" : value.Trim(); } } #endregion /// <summary> /// JSON 分析类 /// </summary> #region JSON public class JSON { private string _json; /// <summary> /// 传入Json /// </summary> /// <param name="json"></param> public JSON(string json) { this._json = json; } /// <summary> /// 获取指定名称的值 /// </summary> /// <param name="name"></param> /// <returns></returns> public object GetValue(string name) { try { string value = this._json.Split(new string[] { "" + name + "\":\"" }, StringSplitOptions.RemoveEmptyEntries)[1]; value = value.Split(new string[] { "\"" }, StringSplitOptions.RemoveEmptyEntries)[0]; return value; } catch (Exception) { return null; } } /// <summary> /// 转化为提供的实体类 /// </summary> /// <typeparam name="T"></typeparam> /// <param name="NewT"></param> /// <returns></returns> public T Convert<T>(T NewT) { PropertyInfo[] properties = typeof(T).GetProperties(); foreach (PropertyInfo propertyInfo in properties) { string Name = propertyInfo.Name; object value = this.GetValue(Name); if (value == null) { NewT = default(T); break; } propertyInfo.SetValue(NewT, value, null); //默认字符型处理. } return NewT; } } #endregion /// <summary> /// ConfigurationHandler 配置节点句柄类 /// </summary> #region ConfigurationHandler public class ConfigurationHandler : IConfigurationSectionHandler { public virtual object Create(Object parent, Object context, XmlNode node) { Hashtable m_Config = new Hashtable(); foreach (XmlNode child in node.ChildNodes) { m_Config.Add(child.Attributes["key"].Value, child.Attributes["value"].Value); } return m_Config; } } #endregion /// <summary> /// UserInfo 用户实体类 /// </summary> #region UserInfo public class UserInfo { private string _nickname; public string nickname { set { this._nickname = value; } get { return this._nickname; } } private string _figureurl; public string figureurl { set { this._figureurl = value; } get { return this._figureurl; } } private string _figureurl_1; public string figureurl_1 { set { this._figureurl_1 = value; } get { return this._figureurl_1; } } private string _figureurl_2; public string figureurl_2 { set { this._figureurl_2 = value; } get { return this._figureurl_2; } } private string _gender; public string gender { set { this._gender = value; } get { return this._gender; } } private string _vip; public string vip { set { this._vip = value; } get { return this._vip; } } private string _level; public string level { set { this._level = value; } get { return this._level; } } private string _is_yellow_year_vip; public string is_yellow_year_vip { set { this._is_yellow_year_vip = value; } get { return this._is_yellow_year_vip; } } } #endregion }
登录
using System; using System.Data; using System.Configuration; using System.Collections; 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 QqConnetSDK; public partial class LoginToQQ : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { GetRequestToken(); } private void GetRequestToken() { QqConnet qc = new QqConnet(); string url = qc.GetAuthorization_Code(); string state = qc.State; Response.Redirect(url); } }
回调访问页面
using System; using System.Data; using System.Configuration; using System.Collections; 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 QqConnetSDK; public partial class QQCallback : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { req(); } private void req() { QqConnet qc = new QqConnet(); if (!qc.VerifyCallback()) { qc.ShowErrMsg("参数缺少."); } //数据令牌 string Access_Token = qc.GetAccess_Token(); //唯一标识 Openid与QQ号一对一对应 string Openid = qc.GetOpenid(Access_Token); //获取当前登录用户 UserInfo User = qc.GetUserInfo(Access_Token, Openid); if (User != null) { this.result.Text = "成功登录."; this.Nickname.Text = User.nickname; this.Figureurl.ImageUrl = User.figureurl; qc.Session("QzoneOauth", User); } } }