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


Posted in PHP onMay 16, 2016

本文实例讲述了Yii2中OAuth扩展及QQ互联登录实现方法。分享给大家供大家参考,具体如下:

php composer.phar require --prefer-dist yiisoft/yii2-authclient "*"

Quick start 快速开始

更改Yii2的配置文件config/main.php,在components中增加如下内容

'components' => [
 'authClientCollection' => [
 'class' => 'yii\authclient\Collection',
 'clients' => [
  'google' => [
  'class' => 'yii\authclient\clients\GoogleOpenId'
  ],
  'facebook' => [
  'class' => 'yii\authclient\clients\Facebook',
  'clientId' => 'facebook_client_id',
  'clientSecret' => 'facebook_client_secret',
  ],
 ],
 ]
 ...
]

更改入口文件,一般是app/controllers/SiteController.php,在function actions增加代码,同时增加回调函数successCallback,大致如下

class SiteController extends Controller
{
 public function actions()
 {
 return [
  'auth' => [
  'class' => 'yii\authclient\AuthAction',
  'successCallback' => [$this, 'successCallback'],
  ],
 ]
 }
 public function successCallback($client)
 {
 $attributes = $client->getUserAttributes();
 // user login or signup comes here
 }
}

在登录的Views中,增加如下代码

<?= yii\authclient\widgets\AuthChoice::widget([
 'baseAuthUrl' => ['site/auth']
])?>

以上是官方的说明文档,下面我们来接入QQ互联

增加QQ登录的组件 我这里是放在 common/components/QqOAuth.php 中,源代码如下

<?php
namespace common\components;
use yii\authclient\OAuth2;
use yii\base\Exception;
use yii\helpers\Json;
/**
 *
 * ~~~
 * 'components' => [
 * 'authClientCollection' => [
 *  'class' => 'yii\authclient\Collection',
 *  'clients' => [
 *  'qq' => [
 *   'class' => 'common\components\QqOAuth',
 *   'clientId' => 'qq_client_id',
 *   'clientSecret' => 'qq_client_secret',
 *  ],
 *  ],
 * ]
 * ...
 * ]
 * ~~~
 *
 * @see http://connect.qq.com/
 *
 * @author easypao <admin@easypao.com>
 * @since 2.0
 */
class QqOAuth extends OAuth2
{
 public $authUrl = 'https://graph.qq.com/oauth2.0/authorize';
 public $tokenUrl = 'https://graph.qq.com/oauth2.0/token';
 public $apiBaseUrl = 'https://graph.qq.com';
 public function init()
 {
 parent::init();
 if ($this->scope === null) {
  $this->scope = implode(',', [
  'get_user_info',
  ]);
 }
 }
 protected function initUserAttributes()
 {
 $openid = $this->api('oauth2.0/me', 'GET');
 $qquser = $this->api("user/get_user_info", 'GET', ['oauth_consumer_key'=>$openid['client_id'], 'openid'=>$openid['openid']]);
 $qquser['openid']=$openid['openid'];
 return $qquser;
 }
 protected function defaultName()
 {
 return 'qq';
 }
 protected function defaultTitle()
 {
 return 'Qq';
 }
 /**
 * 该扩展初始的处理方法似乎QQ互联不能用,应此改写了方法
 * @see \yii\authclient\BaseOAuth::processResponse()
 */
 protected function processResponse($rawResponse, $contentType = self::CONTENT_TYPE_AUTO)
 {
   if (empty($rawResponse)) {
     return [];
   }
   switch ($contentType) {
     case self::CONTENT_TYPE_AUTO: {
       $contentType = $this->determineContentTypeByRaw($rawResponse);
       if ($contentType == self::CONTENT_TYPE_AUTO) {
   //以下代码是特别针对QQ互联登录的,也是与原方法不一样的地方 
         if(strpos($rawResponse, "callback") !== false){
           $lpos = strpos($rawResponse, "(");
           $rpos = strrpos($rawResponse, ")");
           $rawResponse = substr($rawResponse, $lpos + 1, $rpos - $lpos -1);
           $response = $this->processResponse($rawResponse, self::CONTENT_TYPE_JSON);
           break;
         }
   //代码添加结束
         throw new Exception('Unable to determine response content type automatically.');
       }
       $response = $this->processResponse($rawResponse, $contentType);
       break;
     }
     case self::CONTENT_TYPE_JSON: {
       $response = Json::decode($rawResponse, true);
       if (isset($response['error'])) {
         throw new Exception('Response error: ' . $response['error']);
       }
       break;
     }
     case self::CONTENT_TYPE_URLENCODED: {
       $response = [];
       parse_str($rawResponse, $response);
       break;
     }
     case self::CONTENT_TYPE_XML: {
       $response = $this->convertXmlToArray($rawResponse);
       break;
     }
     default: {
       throw new Exception('Unknown response type "' . $contentType . '".');
     }
   }
   return $response;
 }
}

更改 config/main.php 文件,在components中增加,大致如下

'components' => [
 'authClientCollection' => [
   'class' => 'yii\authclient\Collection',
   'clients' => [
     'qq' => [
      'class'=>'common\components\QqOAuth',
      'clientId'=>'your_qq_clientid',
      'clientSecret'=>'your_qq_secret'
    ],
   ],
 ]
]

SiteController.php 就按官方那样子

public function successCallback($client)
{
 $attributes = $client->getUserAttributes();
 // 用户的信息在$attributes中,以下是您根据您的实际情况增加的代码
 // 如果您同时有QQ互联登录,新浪微博等,可以通过 $client->id 来区别。
}

最后在登录的视图文件中 增加QQ登录链接

<a href="/site/auth?authclient=qq">使用QQ快速登录</a>
PHP 相关文章推荐
PHP4 与 MySQL 数据库操作函数详解
Oct 09 PHP
PHP var_dump遍历对象属性的函数与应用代码
Jun 04 PHP
PHP 将逗号、空格、回车分隔的字符串转换为数组的函数
Jun 07 PHP
PHP之APC缓存详细介绍 apc模块安装
Jan 13 PHP
php实现文件下载功能的几个代码分享
May 10 PHP
CI框架开发新浪微博登录接口源码完整版
May 28 PHP
PHP中auto_prepend_file与auto_append_file用法实例分析
Sep 22 PHP
PHP中使用array函数新建一个数组
Nov 19 PHP
twig模板获取全局变量的方法
Feb 05 PHP
在Laravel5.6中使用Swoole的协程数据库查询
Jun 15 PHP
PHP+Oracle本地开发环境搭建方法详解
Apr 01 PHP
php设计模式之享元模式分析【星际争霸游戏案例】
Mar 23 PHP
Yii2 assets清除缓存的方法
May 16 #PHP
php使用curl通过代理获取数据的实现方法
May 16 #PHP
php实现转换html格式为文本格式的方法
May 16 #PHP
php中array_unshift()修改数组key注意事项分析
May 16 #PHP
thinkPHP3.2简单实现文件上传的方法
May 16 #PHP
thinkPHP简单遍历数组方法分析
May 16 #PHP
thinkPHP删除前弹出确认框的简单实现方法
May 16 #PHP
You might like
PHP文章采集URL补全函数(FormatUrl)
2012/08/02 PHP
PHP内置的Math函数效率测试
2014/12/01 PHP
php打印输出棋盘的实现方法
2014/12/23 PHP
PHP实现数组和对象的相互转换操作示例
2019/03/20 PHP
laravel 解决路由除了根目录其他都404的问题
2019/10/18 PHP
php实现文件上传基本验证
2020/03/04 PHP
window.onload追加函数使用示例
2014/03/03 Javascript
jQuery 过滤方法filter()选择具有特殊属性的元素
2014/06/15 Javascript
JavaScript实现N皇后问题算法谜题解答
2014/12/29 Javascript
jQuery左侧大图右侧小图焦点图幻灯切换代码分享
2015/08/19 Javascript
jQuery实现的导航下拉菜单效果示例
2016/09/05 Javascript
vue.js中$watch的用法示例
2016/10/04 Javascript
js判断一个字符串是以某个字符串开头的简单实例
2016/12/27 Javascript
JavaScript面向对象精要(下部)
2017/09/12 Javascript
vue项目webpack中Npm传递参数配置不同域名接口
2018/06/15 Javascript
在vue中使用Autoprefixed的方法
2018/07/27 Javascript
基于Vue 服务端Cookies删除的问题
2018/09/21 Javascript
解决layui追加或者动态修改的表单元素“没效果”的问题
2019/09/18 Javascript
简单了解vue 插值表达式Mustache
2020/07/22 Javascript
[59:32]Liquid vs Fnatic 2019国际邀请赛淘汰赛败者组BO1 8.20.mp4
2020/07/19 DOTA
100行python代码实现跳一跳辅助程序
2018/01/15 Python
pygame游戏之旅 添加键盘按键的方法
2018/11/20 Python
Django Admin中增加导出CSV功能过程解析
2019/09/04 Python
python快速排序的实现及运行时间比较
2019/11/22 Python
PyQt使用QPropertyAnimation开发简单动画
2020/04/02 Python
python mysql中in参数化说明
2020/06/05 Python
Django:使用filter的pk进行多值查询操作
2020/07/15 Python
Flask缓存静态文件的具体方法
2020/08/02 Python
如何用python 操作zookeeper
2020/12/28 Python
6种非常炫酷的CSS3按钮边框动画特效
2016/03/16 HTML / CSS
苹果音乐订阅:Apple Music
2018/08/02 全球购物
小学门卫岗位职责
2013/12/17 职场文书
幼儿园运动会加油词
2014/02/14 职场文书
2014-2015学年工作总结
2014/11/27 职场文书
上级领导检查欢迎词
2015/09/30 职场文书
2016年小学“感恩教师”主题队日活动总结
2016/04/01 职场文书