登陆整合实现-QQ互联认证(ASP.NET版本)

原文:登陆整合实现-QQ互联认证(ASP.NET版本)

首先 我们创建一个qq.ashx的页面,这个页面会跳转到QQ的请求界面

代码如下:

        QQSettingConfig qqSettingConfig = MySiteConfig.GetConfig<QQSettingConfig>();//配置对象 配置QQ的 app id appkey 回调地址
        public void ProcessRequest(HttpContext context)
        {
            context.Response.ContentType = "text/plain";
            string state = new Random(100000).Next(99, 99999).ToString();//随机数
            context.Session["state"] = state;
            string callback = System.Web.HttpUtility.UrlEncode(qqSettingConfig.CallBackAddress + "/QQCallBack.aspx", Encoding.UTF8);//回调处理地址
            string url = string.Format("https://graph.qq.com/oauth2.0/authorize?client_id={0}&response_type=code&redirect_uri={1}&state={2}", qqSettingConfig.APPID, callback, state);//互联地址
            context.Response.Redirect(url);
        }

 

代码比较简单,就是进行一个跳转的操作,其中qqSettingConfig是读取配置文件 里面定义了appid 和appkey 这个需要先到腾讯互联的网站申请

state 是一个随机数,这个随机数我这里写入到session中,腾讯请求后会返回来一个callback的页面 这个页面也是我们自己填写的 ,在c腾讯在返回来请求我们的地址的时候会将这个state传回来 然后外面和我们的session的state进行对比 防止中途被黑客拦截了

 

我这里的回调处理地址就是qqSettingConfig.CallBackAddress + "/QQCallBack.aspx 前面的配置 你可以写死也可以读取配置文件 就是你申请的时候的回调地址

 

然后外面看我们的回调地址

 

回调地址,首先我们也需要配置文件

QQSettingConfig qqSettingConfig = MySiteConfig.GetConfig<QQSettingConfig>();//配置对象 配置QQ的 app id appkey 回调地址

 

然后在pageload事件里面

 

       

protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                try
                {
                    string code = HttpContext.Current.QueryString["code"];
                    string state = HttpContext.Current.QueryString["state"];
                    ValidCodeState(code, state);
                    QQOauthInfo qqOauthInfo = GetOauthInfo(code);
                    string openID = GetOpenID(qqOauthInfo);
                    string nickName = GetUserInfo(qqOauthInfo, openID);
                    if (string.IsNullOrEmpty(nickName))
                    {
                        WriteErrMsg("获取不到昵称");
                    }

                    #region 开始进行注册或者登录
                    OauthUserModel oauthUserModel = BLL.OauthUserBll.GetInfoByOpenId("qq", openID);
                    if (!oauthUserModel.IsNull)
                    {
                        //已经绑定过则登录
                        DealLogin(oauthUserModel);
                    }
                    else
                    {
                        //进行绑定
                        this.TxtRegUserName.Text = nickName;
                        this.hidenNiName.Value = nickName;
                        this.hidenOpenID.Value = openID;
                        this.LabelNiName.Text = nickName;
                        this.LabelOpenID.Text = openID;
                    }
                    #endregion
                }
                catch (Exception ex)
                {
                    //ShowError("出错了:"+ ex.Message);
                }

            }
        }

 

 

腾讯在跳转到我们指定的回调地址的时候 会传回来code 和state 我们首先来验证这两个是否合法

       

/// <summary>
        /// 验证code和state
        /// </summary>
        /// <param name="code"></param>
        /// <param name="state"></param>
        private void ValidCodeState(string code, string state)
        {
            if (string.IsNullOrEmpty(code) || string.IsNullOrEmpty(state))
            {
                ShowError("CODE或者STATE为空");
            }
            if (Session["state"] == null || Session["state"].ToString() != state)
            {
                ShowError("STATE不正确");
            }
        }  

 

1 主要就是验证非空 state和session里面的state进行验证 防止被中途拦截了

然后外面在调用另外的地址 获取token

QQOauthInfo qqOauthInfo = GetOauthInfo(code);
方法如下
 /// <summary>
        /// 获取oauth信息
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        private QQOauthInfo GetOauthInfo(string code)
        {
            string callback = System.Web.HttpUtility.UrlEncode(qqSettingConfig.CallBackAddress + "/QQCallBack.aspx", Encoding.UTF8);
            string url = string.Format("https://graph.qq.com/oauth2.0/token?grant_type={0}&client_id={1}&client_secret={2}&code={3}&redirect_uri={4}", "authorization_code", qqSettingConfig.APPID, qqSettingConfig.APPKEY, code, callback);
            string res = LoadHtmlUserGetType(url, Encoding.UTF8);
            if (!res.Contains("access_token="))
            {
                ShowError("出错了:空access_token");
            }
            QQOauthInfo qqOauthInfo = new QQOauthInfo();
            qqOauthInfo.AccessToken = CutString(res, "access_token=", "&expires_in=");
            qqOauthInfo.ExpiresIn = CutString(res, "&expires_in=", "&refresh_token=");
            qqOauthInfo.RefreshToken = res.Split(new string[] { "&refresh_token=" }, StringSplitOptions.None)[1];
            if (string.IsNullOrEmpty(qqOauthInfo.AccessToken) || string.IsNullOrEmpty(qqOauthInfo.ExpiresIn) || string.IsNullOrEmpty(qqOauthInfo.RefreshToken))
            {
                ShowError("获取access_token等信息为空");
            }
            return qqOauthInfo;
        }
        /// <summary>
        /// 截取字符串中两个字符串中的字符串
        /// </summary>
        /// <param name="str">字符串</param>
        /// <param name="startStr">开始字符串</param>
        /// <param name="endStr">结束字符串</param>
        /// <returns></returns>
        public string CutString(string str, string startStr, string endStr)
        {
            int begin, end;
            begin = str.IndexOf(startStr, 0) + startStr.Length; //开始位置
            end = str.IndexOf(endStr, begin);            //结束位置
            return str.Substring(begin, end - begin);   //取搜索的条数,用结束的位置-开始的位置,并返回
        }  

        /// <summary>
        /// 通过GET方式获取页面的方法
        /// </summary>
        /// <param name="urlString">请求的URL</param>
        /// <param name="encoding">页面编码</param>
        /// <returns></returns>
        public string LoadHtmlUserGetType(string urlString, Encoding encoding)
        {
            HttpWebRequest httpWebRequest = null;
            HttpWebResponse httpWebRespones = null;
            Stream stream = null;
            string htmlString = string.Empty;
            try
            {
                httpWebRequest = WebRequest.Create(urlString) as HttpWebRequest;
            }
            catch (Exception ex)
            {
                throw new Exception("建立页面请求时发生错误!", ex);
            }
            httpWebRequest.UserAgent = "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 2.0.50727; Maxthon 2.0)";
            try
            {
                httpWebRespones = (HttpWebResponse)httpWebRequest.GetResponse();
                stream = httpWebRespones.GetResponseStream();
            }
            catch (Exception ex)
            {
                throw new Exception("接受服务器返回页面时发生错误!", ex);
            }
            StreamReader streamReader = new StreamReader(stream, encoding);
            try
            {
                htmlString = streamReader.ReadToEnd();
            }
            catch (Exception ex)
            {
                throw new Exception("读取页面数据时发生错误!", ex);
            }
            streamReader.Close();
            stream.Close();
            return htmlString;
        } 

 

返回来 我封装了一个实体对象 

   

public class QQOauthInfo
    {
        public string AccessToken { get; set; }
        public string ExpiresIn { get; set; }
        public string RefreshToken { get; set; }
    } 

 

代码没什么 就是获取返回来的token 和有效期expresein等

 

2 这里我用了本方法 就是截取字符串,其实他是一个json对象的, 同学们可以使用json解析工具,对他进行解析

 

获得了这三个之后 我们再来获得openid

string openID = GetOpenID(qqOauthInfo);
方法如下
        /// <summary>
        /// 获取QQ账号的OpenID
        /// </summary>
        /// <param name="qqOauthInfo"></param>
        /// <returns></returns>
        private string GetOpenID(QQOauthInfo qqOauthInfo)
        {
            string res = LoadHtmlUserGetType("https://graph.qq.com/oauth2.0/me?access_token=" + qqOauthInfo.AccessToken, Encoding.UTF8);
            if (!res.Contains("openid"))
            {
                WriteErrMsg("出错了:获取用户的openid出错");
            }
            return CutString(res, @"openid"":""", @"""}");
        } 

 

 

很简单 就是继续请求一个地址 然后再截取出openid

 

有了openid后,我们继续获取用户名

string nickName = GetUserInfo(qqOauthInfo, openID); 

方法如下
        /// <summary>
        /// 获取QQ昵称
        /// </summary>
        /// <param name="qqOauthInfo"></param>
        /// <param name="openID"></param>
        /// <returns></returns>
        private string GetUserInfo(QQOauthInfo qqOauthInfo, string openID)
        {
            string urlGetInfo = string.Format(@"https://graph.qq.com/user/get_user_info?access_token={0}&oauth_consumer_key={1}&openid={2}", qqOauthInfo.AccessToken, qqSettingConfig.APPID, openID);
            string resUserInfo = LoadHtmlUserGetType(urlGetInfo, Encoding.UTF8);
            if (!resUserInfo.Contains("\"msg\": \"\""))
            {
                WriteErrMsg("出错了:获取用户信息出错");
            }
            return CutString(resUserInfo, @"""nickname"": """, @""",");
        } 

 

 

 

也是一样 请求一个地址 然后截取出nickname

 

有了这个nickname后 我们就可以 进行下一步操作了

if (string.IsNullOrEmpty(nickName))
                    {
                        ShowError("获取不到昵称");
                    }
                    #region 开始进行注册或者登录
                    OauthUserModel oauthUserModel = BLL.OauthUserBll.GetInfoByOpenId("qq", openID);
                    if (!oauthUserModel.IsNull)
                    {
                        //已经绑定过则登录
                        DealLogin(oauthUserModel);
                    }
                    else
                    {
                        //进行绑定
                        this.TxtRegUserName.Text = nickName;
                        this.hidenNiName.Value = nickName;
                        this.hidenOpenID.Value = openID;
                        this.LabelNiName.Text = nickName;
                        this.LabelOpenID.Text = openID;
                    }
                    #endregion 

 

 

比如 我们先检查我们的数据库 改账号是否已经绑定过了,注意 我们要保存openid 来判断 因为openid是唯一标记这个QQ账号的 用户名是不能标记的

BLL.OauthUserBll.GetInfoByOpenId("qq", openID);

 

为了统一一张表,方便以后扩展其他的登录整合 这里加了个“qq”的标志字段

 

这张表的sql语句如下:

if exists(
   select 1 from sys.systable
   where table_name='PE_C_OauthUser'
     and table_type in ('BASE', 'GBL TEMP')
) then
    drop table PE_C_OauthUser
end if;

/*==============================================================*/
/* Table: PE_C_OauthUser                                        */
/*==============================================================*/
create table PE_C_OauthUser
(
   ID                   int                            not null,
   NiName               nvarchar(50)                   null,
   UserName             nvarchar(50)                   null,
   Type                 nvarchar(50)                   null,
   AddTime              datetime                       null,
   Status               int                            null,
   OpenID               nvarchar(150)                  null,
   UserID               int                            null,
   constraint PK_PE_C_OAUTHUSER primary key clustered (ID)
);

comment on table PE_C_OauthUser is
'用户和QQ或者微信等其他的Oauth关联';

comment on column PE_C_OauthUser.ID is
'主键ID';

comment on column PE_C_OauthUser.NiName is
'昵称从QQ或者微信取得的昵称';

comment on column PE_C_OauthUser.UserName is
'我方系统用户名';

comment on column PE_C_OauthUser.Type is
'类型:如QQ WEIXIN';

comment on column PE_C_OauthUser.AddTime is
'添加时间';

comment on column PE_C_OauthUser.Status is
'状态';

comment on column PE_C_OauthUser.OpenID is
'是QQ则openid  微信则';

comment on column PE_C_OauthUser.UserID is
'我方系统用户ID';

if exists(
   select 1 from sys.systable
   where table_name='PE_C_OauthUser'
     and table_type in ('BASE', 'GBL TEMP')
) then
    drop table PE_C_OauthUser
end if;

/*==============================================================*/
/* Table: PE_C_OauthUser                                        */
/*==============================================================*/
create table PE_C_OauthUser
(
   ID                   int                            not null,
   NiName               nvarchar(50)                   null,
   UserName             nvarchar(50)                   null,
   Type                 nvarchar(50)                   null,
   AddTime              datetime                       null,
   Status               int                            null,
   OpenID               nvarchar(150)                  null,
   UserID               int                            null,
   constraint PK_PE_C_OAUTHUSER primary key clustered (ID)
);

comment on table PE_C_OauthUser is
'用户和QQ或者微信等其他的Oauth关联';

comment on column PE_C_OauthUser.ID is
'主键ID';

comment on column PE_C_OauthUser.NiName is
'昵称从QQ或者微信取得的昵称';

comment on column PE_C_OauthUser.UserName is
'我方系统用户名';

comment on column PE_C_OauthUser.Type is
'类型:如QQ WEIXIN';

comment on column PE_C_OauthUser.AddTime is
'添加时间';

comment on column PE_C_OauthUser.Status is
'状态';

comment on column PE_C_OauthUser.OpenID is
'是QQ则openid  微信则';

comment on column PE_C_OauthUser.UserID is
'我方系统用户ID';

如果发现已经绑定了 则直接登录就可以了

if (!oauthUserModel.IsNull)
                    {
                        //已经绑定过则登录
                        DealLogin(oauthUserModel);
                    }

 

 

登录的方法 根据你自己系他来实现

 

否则的话 就将这些nickname 等信息 写到textbox hidden等控件中 让用户来进行操作

 

 //进行绑定
                        this.TxtRegUserName.Text = nickName;
                        this.hidenNiName.Value = nickName;
                        this.hidenOpenID.Value = openID;
                        this.LabelNiName.Text = nickName;

                        this.LabelOpenID.Text = openID;

 

 

用户可以选择两种方式 进行

一种是注册新的账号,然后绑定 ,另外一种是绑定已经注册的账号

 

这两种方式 都需要输入密码 第一种要输入两次 需要实现 同时注册 同时添加到绑定表 就是上面的表 另外一种就是直接插入绑定表就可以了

这里面的代码 就不贴出来了,用户根据自己的办法来实现

绑定新账号 的方式 就是先注册一个 然后插入绑定表 然后登录

 

绑定已有账号的方式 就先判断密码是否正确 正确就插入绑定表 然后登录

 

//添加到绑定表
            OauthUserModel oauthUserModelNew = new OauthUserModel();
            oauthUserModelNew.AddTime = DateTime.Now;
            oauthUserModelNew.NiName = this.hidenNiName.Value;
            oauthUserModelNew.OpenID = this.hidenOpenID.Value;
            oauthUserModelNew.Status = 1;
            oauthUserModelNew.Type = "qq";
            oauthUserModelNew.UserID = usersInfo.UserId;
            oauthUserModelNew.UserName = usersInfo.UserName;
            if (!BLL.OauthUserBll.Add(oauthUserModelNew))
            {
                ShowError("绑定失败");
            }  

 

 感谢阅读,希望对你有帮助,更多资料 可以加群讨论的....

 

 

时间: 2024-11-01 13:30:06

登陆整合实现-QQ互联认证(ASP.NET版本)的相关文章

asp.net网站如何获取访问客户已经登陆了的QQ

问题描述 asp.net网站如何获取访问客户已经登陆了的QQ 解决方案 解决方案二:对于这种问题,只能路过下,打个酱油解决方案三:alert('你登录的QQ号是多少?');解决方案四:学习学习学习学习解决方案五:写com查进程应该可以的解决方案六:引用4楼hudsonhuang的回复: 写com查进程应该可以的 刚upgrade了一下,用c#写容易太多了http://www.alixixi.com/Dev/Web/ASPNET/aspnet1/2007/2007070765858.html

牟长青:谈谈使用QQ互联对论坛的帮助

记得去年康盛刚被腾讯收购的时候,站长圈的朋友就在议论,腾讯的收购,会给康盛旗下的产品,特别是discuz带来什么样得变化.当时就有不少站长朋友在猜测,腾讯会不会弄个一键登录.只要用QQ号码,就能登陆使用DZ程序的所有论坛.慢慢没想到猜测最后成为了事实. 让我想起曾经做论坛推广时候的一个梦想,有一个万能账户,所有论坛都弄个账户密码一样的ID.以后需要做论坛推广的时候,随便打开一个论坛,都可以登陆,从而提高推广的效率. 在国外早就有了这样的通行证,一个账号可以登陆多个网站,方便了用户,也方便了网站.

QQ互联全面开放 助网站获取流量与用户

中介交易 SEO诊断 淘宝客 云主机 技术大厅 日前,QQ互联宣布推出多个插件版,包括QQ互联插件版 for Discuz! 7.2/X1.5以及QQ互联插件版for phpwind 8.0/8.3/8.5.至此,国内主要的两大论坛系统Discuz! 和phpwind都已纳入QQ互联开放体系,这意味着QQ互联将覆盖90%以上的中文论坛,QQ互联正用实际行动来诠释开放,并将其开放理念落到实处,同步专题(http://discuz.qq.com/activity/connectOpen?adtag=

PHP版QQ互联OAuth示例代码分享_php技巧

由于国内QQ用户的普遍性,所以现在各大网站都尽可能的提供QQ登陆口,下面我们来看看php版,给大家参考下 /** * QQ互联 oauth * @author dyllen * */ class Oauth { //取Authorization Code Url const PC_CODE_URL = 'https://graph.qq.com/oauth2.0/authorize'; //取Access Token Url const PC_ACCESS_TOKEN_URL = 'https:

腾讯即将放弃“超级QQ”服务 将其整合到QQ会员

腾讯即将放弃"超级QQ"服务 将其整合到QQ会员腾讯QQ旗下服务项目五花八门,基本都是变着法儿让你花钱,而且经常变来变去,很难预料.近日又有消息称,腾讯即将放弃"超级QQ"服务,将其整合到QQ会员里.其实这一年多来经常有超级QQ.QQ会员将会合并的消息传出,腾讯一直予以否认,但这一次,看上去是板上钉钉了.超级QQ是一项很古老的服务了,诞生于2006年,最大特点就是不登陆也能24小时显示移动在线,并享受2倍的等级加速,从而快速积累在线时长.提高个人等级,此外还有其他一

QQ互联带动许嵩论坛人气剧增 欲打造最大明星论坛

中介交易 SEO诊断 淘宝客 云主机 技术大厅 近日,记者从许嵩(Vae)官方论坛了解到,其会员数量已经突破50万,最高同时在线人数达到33504,这是自2010年11月以来,许嵩官方论坛接入QQ互联后发生的显著变化. 据悉,许嵩官方论坛成立于2006年,由许嵩一手创建,是目前全球最大V迷交流基地.最权威许嵩信息发布中心.自去年年底,历时不到半年时间,许嵩论坛的每日注册用户数.帖子分享次数频频刷新,引起了众多粉丝站点的关注.为此,我们特别访问了许嵩官方论坛运营总监张建. QQ一键登录方便快捷聚人

Yii2中OAuth扩展及QQ互联登录实现方法_php实例

本文实例讲述了Yii2中OAuth扩展及QQ互联登录实现方法.分享给大家供大家参考,具体如下: 复制代码 代码如下: php composer.phar require --prefer-dist yiisoft/yii2-authclient "*" Quick start 快速开始 更改Yii2的配置文件config/main.php,在components中增加如下内容 'components' => [ 'authClientCollection' => [ 'cl

QQ互联:合作网站给力法宝

摘要: 如今,开放已成为全球互联网行业最炙手可热的概念,国外谷歌.FaceBook.苹果等巨头早已纷纷借开放抢滩,国内在去年也有腾讯等行业先锋加入到开放这一行列,2010年也因此成为中国 QQ互联:合作网站给力法宝 不久前,腾讯全面推出了基于QQ空间的QQ互联计划,旨在帮助传统网站.论坛主.媒体机构和个人等合作伙伴搭建信息交流和沟通的桥梁.该计划由喜欢组件.分享组件和连接QQ空间等九大社交组件组成,一经推出,便得到了广大网站主的关注与追捧. QQ空间堪称目前国内最大的社交化分享网站,并带动合作网

凤凰视频接入QQ互联 优质内容获N次传播效果

中介交易 http://www.aliyun.com/zixun/aggregation/6858.html">SEO诊断 淘宝客 云主机 技术大厅 近日,全球著名的华语媒体--凤凰卫视旗下凤凰视频全面合作"QQ互联".第三方数据显示,凤凰视频与QQ互联合作运营仅2周时间,日增用户即高达6000人,且目前该数字仍在持续增长中.凤凰视频的优质内容也因QQ空间和腾讯微博的庞大粉丝量而得到了良好的N次传播效果 . 对此,凤凰视频相关负责人表示,与"QQ互联"