第三方登录之QQ登录从入门到填坑

【推荐阅读】微服务还能火多久?>>> 第三方登录之QQ登录从入门到填坑

1.前言

之前写了一篇关于微信登录的实战文章,发现挺多人看的,下面把微信的粑粑(QQ)也整理一下,首先登陆QQ互联首页https://connect.qq.com/进行个人/企业认证。大概审核时间在一周左右。认证通过之后创建应用这里主要用到应用的APP ID 和 APP Key  这两个参数。当然还需要填写一下回调地址就是请求qq接口获取code参数回调给你的地址,话不多说,我们开始QQ登录之旅吧

代码分享:https://github.com/mtdgclub/qqlogin

2.回顾OAuth协议基本原理

OAuth 就是一种授权机制。数据的所有者告诉系统,同意授权第三方应用进入系统,获取这些数据。系统从而产生一个短期的进入令牌(token),用来代替密码,供第三方应用使用。

PS:只要知道了令牌,就能进入系统。系统一般不会再次确认身份,所以令牌必须保密,泄漏令牌与泄漏密码的后果是一样的。 这也是为什么令牌的有效期,一般都设置得很短的原因。

比如QQ登录授权:

第三方登录之QQ登录从入门到填坑

3.接入QQ登录SDK

3.1接入前的条件和开放平台账号申请

  • 官网:http://connect.qq.com
  • 申请AppID和AppKey
  • 配置好回调地址

3.2引入官方SDK

前往官网下载你熟悉编程语言的SDK,这边默认是PHP,所以phper可以在我的代码分享直接使用QQ_PHP_SDK_v2.2.zip包。

3.2.1SDK参数配置

  • 务必在QQ开放平台设置好回调地址,然后再项目文件下写好回调地址的文件callback.php
  • 访问SDK包,配置SDK参数,配置完成后删除冗余文件剩下API文件夹

第三方登录之QQ登录从入门到填坑

3.2.2 SDK核心方法解读

登录授权相关的三个主要类

  • 配置读写与SESSION存取Recorder.class.php
//-------读取配置文件
$incFileContents = file(ROOT."comm/inc.php");
$incFileContents = $incFileContents[1];
$this->inc = json_decode($incFileContents);
  • 基于CURL库的get和post请求URL.class.php
//combineURL拼接URL函数
foreach($keysArr as $key => $val){
    $valueArr[] = "$key=$val";
}
//使用&拼接参数键值对
$keyStr = implode("&",$valueArr);
$combined .= ($keyStr);
  • get方式请求资源
public function get($url, $keysArr)
  • post方式请求资源
public function post($url, $keysArr, $flag = 0)
  • Oauth相关URL动态拼接与token操作Oauth.class.php
/**
 * 拼接QQ登录URL
 */
public function qq_login(){...}

3.3整合QQ登录SQK到应用中

3.3.1SDK优化处理

优化目的:

  • SDK太老,无人维护,我们需要调整文件和目录结构
  • SDK中常量名可能与我们项目冲突,批量替换SDK常量名称

将comm文件夹内的文件分别移动代码到指定的文件里面,最终实现删除comm文件夹的效果,然后再入口文件修改常量的定义名称,记得全文搜索,避免与以后项目起冲突,具体请看我修改好的sdk文件夹,步骤如下:

  • 将常量CLASS_PATH替换成QQ_CONNECT_SDK_CLASS_PATH
  • 在qqConnectAPI.php定义常量
define("QQ_CONNECT_SDK_CLASS_ROOT",dirname(__FILE__)."/");
define("QQ_CONNECT_SDK_CLASS_PATH",QQ_CONNECT_SDK_CLASS_ROOT."class/");
  • 删除comm文件
  • 删除qqConnectAPI.php的配置引入
//require_once(dirname(__FILE__)."/comm/config.php");
  • 在Recorder.class.php中添加配置信息代码
//-------读取配置文件 优化代码
$this->inc->appid = '';
$this->inc->appkey = '';
$this->inc->callback = QQ_CONNECT_SDK_ROOT . 'callback.php';
$this->inc->scope = 'get_user_info';
$this->inc->errorReport = true;
$this->inc->storageType = 'file';

3.3.2调用API开发实例

  • debug调试输出函数,详见debug.php文件
<?php
/**
 * 调式输出函数
 * @param mix $val 调试输出源数据
 * @param bool $dump 是否启用var_dump调式
 * @param bool $exit 是否在调试结束后设置断点
 */
function debug($val, $dump = false, $exit = true)
{
    //自动获取调试函数名称$func
    if ($dump) {
        $func = 'var_dump';
    } else {
        $func = (is_array($val) || is_object($val)) ? 'print_r' : 'printf';
    }
    //输出到html
    header('Content-type:text/html;charset=utf-8');
    echo '<pre>debug output:<hr/>';
    $func($val);
    echo '</pre>';
    if ($exit) exit();
}
  • 访问qq登陆页面,详见qqlogin.php
<?php
require_once 'debug.php';
require_once 'qqLoginSDK/qqConnectAPI.php';
//访问qq登陆页面
$oauth = new Oauth();
$oauth->qq_login();
  • 在回调地址中获得code和accesstoken,通过accesstoken获得openID,详见callback.php
<?php
require_once 'debug.php';
require_once 'qqLoginSDK/qqConnectAPI.php';
$code = $_GET['code'];
//请求accesstoken
$oauth = new Oauth();
$accessToken = $oauth->qq_callback();
//获得openID
$openid = $oauth->get_openid();
//存储到cookie
setcookie('qq_accesstoken', $accessToken, time() + 86400);
setcookie('qq_openid', $openid, time() + 86400);
header('location:index.php');

注意:openID是QQ用户在第三方站点的唯一标识,同一个QQ用户在不同站点使用QQ登录openID始终一样

  • 获得用户数据并存储到本地数据库,详见index.php
$qc = new QC($_COOKIE['qq_accesstoken'], $_COOKIE['qq_openid']);
$userinfo = $qc->get_user_info();
debug($userinfo);