开放平台-web实现QQ第三方登录

应用场景

web应用通过QQ登录授权实现第三方登录。

操作步骤

1  注册成为QQ互联平台开发者,http://connect.qq.com/

2  准备一个可访问的域名,如dev.foo.com

3  创建网页应用,配置必要信息,其中包括域名以及回调地址;

其中域名需要验证,需确保对域名主机有足够的控制权限

4  获取应用appID、appKey进行开发

登录流程

开发平台的登录授权采取oauth2.0机制,这也是目前几乎所有互联网开放平台所采取的方式。

需更多了解oauth2.0可参考阮老师的文章: http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html

实现方式

client-side

流程:

前端页面通过Implict方式 登录授权 -> 回调获得accessToken -> 获取openid -> 同步用户信息并登录

为了保证数据安全,在获取用户信息并登录这一步必须由服务端实现。

这种方式的开发相对便捷,也是后面的实战案例将要采取的方式。

server-side

流程:

由server端页面跳转到登录授权页面(Authorization code方式) -> 回调获得code -> 置换accessToken -> 获取openid -> 同步用户信息并登录

可参考:http://wiki.connect.qq.com/%E5%BC%80%E5%8F%91%E6%94%BB%E7%95%A5_server-side

SDK使用

JSSDK  可快捷实现前端登录授权的功能,可自定制登录按钮

使用文档:http://wiki.connect.qq.com/js_sdk%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E

缺点:存在浏览器兼容风险,此外登录按钮UI的定制也存在受限

JavaSDK  屏蔽了oauth授权的复杂度,方便后端实现授权及api操作

缺点:增加依赖jar包,项目容易变得臃肿,尤其是当前项目已经存在oauth功能实现时可不必采用。

案例实战

功能描述

clientside + server-side 通过QQ网页授权登录,并获取用户信息

1  本地开发环境准备

修改hosts文件将dev.foo.com映射到127.0.0.1;

本地服务器以80端口启动, windows下可能会出现80端口被系统进程占用的情况,解决方法可参考 http://www.cnblogs.com/littleatp/p/4414578.html

本地服务器启动后,以dev.foo.com的域名进行访问,在QQ登录授权时可通过域名验证这一步

2  登录跳转页面

<html>
     <head>
        <title>QQ登录跳转</title>
        <script src="http://lib.sinaapp.com/js/jquery/1.7.2/jquery.min.js" type="text/javascript"></script>

        <script type="text/javascript">

        //切割字符串转换参数表
        function toParamMap(str){
             var map = {};
             var segs = str.split("&");
             for(var i in segs){
                 var seg = segs[i];
                 var idx = seg.indexOf(‘=‘);
                 if(idx < 0){
                     continue;
                 }
                 var name = seg.substring(0, idx);
                 var value = seg.substring(idx+1);
                 map[name] = value;
             }
             return map;
         }

        //隐式获取url响应内容(JSONP)
        function openImplict(url){
            var script = document.createElement(‘script‘);
            script.src = url;
            document.body.appendChild(script);
        }

        //获得openid的回调
        function callback(obj)
        {
           var openid = obj.openid;
           $("#openid").text(openid);

           //跳转服务端登录url
           var resulturl = "@{openapi.QQs.login_result()}";
           var accessToken = $("#accessToken").text();

           //向服务端传输access_token及openid参数
           document.location.href=resulturl + "?access_token=" + accessToken + "&openid=" + openid;
        }

        </script>
     </head>

     <body>
            <p>AccessToken:<span id="accessToken"></span>--ExpireIn<span id="expire"></span></p>
            <p>OpenID:<span id="openid"></span></p>

     <!-- 执行脚本 -->
     <script type="text/javascript">

     //应用的APPID
     var appID = "101207268";

     //登录授权后的回调地址,设置为当前url
     var redirectURI = "@@{openapi.QQs.login()}";

     //初始构造请求
     if (window.location.hash.length == 0)
     {
        var path = ‘https://graph.qq.com/oauth2.0/authorize?‘;
        var queryParams = [‘client_id=‘ + appID,
                           ‘redirect_uri=‘ + redirectURI,
                           ‘scope=‘ + ‘get_user_info,list_album,upload_pic,add_feeds,do_like‘,‘response_type=token‘];

        var query = queryParams.join(‘&‘);
        var url = path + query;
        window.location.href= url;
     }
     //在成功授权后回调时location.hash将带有access_token信息,开始获取openid
     else
     {
        //获取access token
        var accessToken = window.location.hash.substring(1);
        var map = toParamMap(accessToken);

        //记录accessToken
        $("#accessToken").text(map.access_token);
        $("#expire").text(map.expires_in);

        //使用Access Token来获取用户的OpenID
        var path = "https://graph.qq.com/oauth2.0/me?";
        var queryParams = [‘access_token=‘+map.access_token, ‘callback=callback‘];
        var query = queryParams.join(‘&‘);
        var url = path + query;
        openImplict(url);
     }

     </script>
     </body>
</html>

功能描述

页面在第一次打开时跳转到QQ登录授权页面;

授权成功之后回到当前页面通过url参数(hash串)获得accessToken;

此后可通过jsonp方式获取用户的openid,url如:

https://graph.qq.com/oauth2.0/me?access_token=YOUR_ACCESS_TOKEN

获取到用户OpenID,返回包如下(JSONP方式获取):

callback( {"client_id":"YOUR_APPID","openid":"YOUR_OPENID"} )

将access_token及openid传到服务端进行处理

3  server端获取用户信息

接收openid的页面方法

      /**
     * 登录结果
     *
     * @param access_token
     * @param openid
     */
    public static void login_result(String access_token, String openid) {
        //调用api获取qq用户信息
        QQUserInfo user = QQApi.getUserInfo(access_token, openid);

        //此时若取得user信息,则可以进行保存,并执行用户登录操作
        ....

        //登录成功后跳转
        redirect(xxx);
    }

QQApi的实现

/**
 * QQ互联API
 *
 * <pre>
 * 登录流程:
 *
 * 1 前端跳转qq授权页面
 * 2 js获得access_token
 * 3 通过jsonp方式获得openid
 * 4 server端根据上传的access_token及openid获取用户信息,如昵称、头像
 *
 * 参考文档:
 * http://wiki.connect.qq.com/%E5%BC%80%E5%8F%91%E6%94%BB%E7%95%A5_client-side#Step2.EF.BC.9A.E8.8E.B7.E5.8F.96AccessToken
 * </pre>
 *
 * @author xxx
 * @createDate 2015年3月10日
 *
 */
public class QQApi {

    public static String appId = "xxx";
    public static String appSecret = "xxx";

    public static String baseUrl = "https://graph.qq.com";

    protected static final String URL_GET_USERINFO = baseUrl
            + "/user/get_user_info?access_token=%s&oauth_consumer_key=%s&openid=%s";

    protected static final long ACCESS_TIMEOUT = 15;

    protected static final String DEF_APP_TOKEN_EXPIRE = "3h";

    /**
     * 获取用户信息
     *
     * <pre>
     * http://wiki.connect.qq.com/get_user_info
     *
     *
     * 调用地址:
     * https://graph.qq.com/user/get_user_info
     * 参数
     *   access_token=*************&
     *   oauth_consumer_key=12345&
     *   openid
     *
     * 返回结果如下:
     * {
     *     "ret": 0,
     *     "msg": "",
     *     "is_lost": 0,
     *     "nickname": "小吞",
     *     "gender": "女",
     *     "province": "广东",
     *     "city": "广州",
     *     "year": "1993",
     *     "figureurl": "http://qzapp.qlogo.cn/qzapp/101207268/982C9FEADAF7B242C5069B8F390784BF/30",
     *     "figureurl_1": "http://qzapp.qlogo.cn/qzapp/101207268/982C9FEADAF7B242C5069B8F390784BF/50",
     *     "figureurl_2": "http://qzapp.qlogo.cn/qzapp/101207268/982C9FEADAF7B242C5069B8F390784BF/100",
     *     "figureurl_qq_1": "http://q.qlogo.cn/qqapp/101207268/982C9FEADAF7B242C5069B8F390784BF/40",
     *     "figureurl_qq_2": "http://q.qlogo.cn/qqapp/101207268/982C9FEADAF7B242C5069B8F390784BF/100",
     *     "is_yellow_vip": "0",
     *     "vip": "0",
     *     "yellow_vip_level": "0",
     *     "level": "0",
     *     "is_yellow_year_vip": "0"
     * }
     * </pre>
     *
     * @param accessToken
     * @return
     */
    public static QQUserInfo getUserInfo(String accessToken, String openid) {
        if (StringUtils.isEmpty(accessToken) || StringUtils.isEmpty(openid)) {
            return null;
        }

        String url = String.format(URL_GET_USERINFO, accessToken, appId, openid);

        String resultString = DefaultHttp.get(url, ACCESS_TIMEOUT, GlobalConstants.UTF_8);

        Logger.debug("[sso-qq]get userinfo. use url ‘%s‘", url);

        QQUserInfo userinfo = JsonUtil.fromJson(resultString, QQUserInfo.class);
        if (userinfo == null || !userinfo.hasGot()) {
            Logger.debug("[sso-qq]get userinfo failed, with result of ‘%s‘", resultString);
            return null;
        }

        Logger.debug("[sso-qq]get userinfo success, with result of ‘%s‘", resultString);
        return userinfo;
    }

常见问题

网页跳转提示 "redirect_uri_mismatch"

通常是应用配置中的域名与当前开发服务器访问地址不一致导致,参照案例中的本地开发环境准备小节

api调用返回错误

查看返回的ret字段,对于非0值的ret则表示异常结果,可通过以下地址查询错误原因:

http://wiki.connect.qq.com/%E5%85%AC%E5%85%B1%E8%BF%94%E5%9B%9E%E7%A0%81%E8%AF%B4%E6%98%8E

接口调用过于频繁或超过限制

应用系统可做好access_token的存储,此外对于用户数据(昵称、头像)也做好缓存或持久化,以减少接口的调用频度。

时间: 2024-10-01 06:52:22

开放平台-web实现QQ第三方登录的相关文章

开放平台-web实现人人网第三方登录

应用场景 web应用通过人人网登录授权实现第三方登录. 操作步骤 1  注册成为人人网开放平台开发者 http://app.renren.com/developers/devinfo 2  准备一个可访问的域名,如dev.foo.com 3  创建网页应用,配置必要信息,其中包括根域名.图标信息 4  获取应用appID.appKey进行开发 登录流程 采用server-side方式实现登录授权,流程如下 流程描述 1  server端页面跳转到登录授权页面(Authorization code

Android应用之最新版本SDKV2.4实现QQ第三方登录

为什么要写这篇博客呢?因为,我在做这个第三方登录的时候,找了很多资料,发现要么就是过时了,要么就是说的很不清楚,很罗嗦,而且很多都是一些小 demo,不是什么实例,甚至连腾讯官方的文档都有这个问题,文档中很多地方用的不是最新的sdk写的示例,用最新版本的sdk发现根本没法达到预期的效 果,很多api已经发生了变化,demo还是用的原来的api中的方法,最坑爹是demo下载下来还要一个支持的库文件,但是sdk中又没有提供.. 自己跌跌撞撞,查找资料,整合,弄了几个小时,终于把它给整出来了,用在了开

Android应用之——最新版本SDK V2.4实现QQ第三方登录

为什么要写这篇博客呢?因为,我在做这个第三方登录的时候,找了很多资料,发现要么就是过时了,要么就是说的很不清楚,很罗嗦,而且很多都是一些小demo,不是什么实例,甚至连腾讯官方的文档都有这个问题,文档中很多地方用的不是最新的sdk写的示例,用最新版本的sdk发现根本没法达到预期的效果,很多api已经发生了变化,demo还是用的原来的api中的方法,最坑爹是demo下载下来还要一个支持的库文件,但是sdk中又没有提供.. 自己跌跌撞撞,查找资料,整合,弄了几个小时,终于把它给整出来了,用在了开发的

QQ第三方登录

QQ第三方登录 在Android应用程序的开发过程中,很多时候需要加入用户登录/注册模块.除了自己动手设计登录界面并实现相应功能外,现在还可以借助百度.腾讯等开发者平台提供的第三方账号登录模块.最近研究了友盟的社会化分享组件,对其提供的SDK中第三方登录的QQ模块进行了测试.本篇文章先对友盟用户注册.SDK下载及案例的下载做一个简单的介绍,然后针对测试程序的过程及代码进行详细的描述. 顺便提一点,进入友盟的主页及SDK下载页面之后,会发现其支持Android.IOS等多个环境下的应用程序开发,感

iOS5.0以上使用新浪微博开放平台OAuth 续(及解决登录无效问题)

新浪微博开放平台为第三方应用提供了简便的合作模式,满足了手机用户和平板电脑用户随时随地分享信息的需求.通过调用平台的api即可实现很多微博上的功能. 本篇主要目的是记录新浪微博移动SDK iOS版本的在iOS5下的嵌入和使用. 1.申请一个新浪微博的移动应用 . 申请地址:http://open.weibo.com/development,申请后得到App key 和 App Secret 2.下载iOS_sdk 下载地址:http://open.weibo.com/wiki/SDK#iOS_S

使用QQ第三方登录时,手机应用和网站应用对同一个QQ号,获取到的openid不一样

使用QQ第三方登录时,手机应用和网站应用对同一个QQ号,获取到的openid不一样openid生成是根据应用的appid和QQ号的一些信息加密生成,对于一个appid和QQ号来说,openid是唯一的手机应用和网站应用使用的appid不是同一个,所以,获取到的openid也不会相同 那么问题来了同一个QQ,通过手机端第三方登录进去,和通过网站登录进去,因为openid不一样,会生成两个用户 解决方法: 给[email protected]发送邮件,内容格式: 第三方登录,web端返回的openi

javaEE SSH框架 qq第三方登录及用户绑定

前几天刚申请好域名,下面实现网站的qq第三方登录的功能,javaEE的SSH框架.(一些细节问题没有处理,只是大体上实现) 一:首先说一下需求,第一次使用qq第三方登录的用户需要绑定已有的网站用户名,绑定成功后进入首页.以后再使用qq第三方登录就直接进入网站首页. 二:要想使用qq第三方首先需要申请应用(需要有自己的域名) (1)登录qq互联网站申请应用,http://connect.qq.com/ (2)创建应用 (3)创建好之后还是可以修改的,这里回调地址我用的是域名+back.jsp界面(

Android 实现QQ第三方登录

在项目中需要实现QQ第三方登录,经过一番努力算是写出来了,现在总结以下,以防以后遗忘,能帮到其他童鞋就更好了. 首先肯定是去下载SDK和DEMO http://wiki.open.qq.com/wiki/mobile/SDK下载 本文是我自己整合后的简单DEMO. 先看下效果图吧 小码哥Html5教程,免费随你看 [点击进入] 24小时阅读30000+,48小时视频下载50000+ H5,JS,CSS,0基础学完独立开发网站/APP! 查 看 小码哥Html5教程,免费随你看 [点击进入] 24

javaEE SSH框架 qq第三方登录及用户绑定(java sdk版)

之前有位朋友用js sdk实现了 SSH框架下的qq第三方登录功能,但是我发现使用js sdk 有些无法克服的安全问题,所以我改用java sdk来实现这个功能! 如图,使用java sdk时,回调地址应设置为一个.action链接.(注意!修改回调地址的话,官方不会及时给你审核通过,有的人修改回调地址后一年 官方都没给他审核通过,这意味着[修改回调地址不如 要重新申请一个域名!重新申请一次网站接入]) 使用官方给定的Sdk4J.jar时 控制台会打印许多log信息,这严重影响项目的运行效率,所