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 相关文章推荐
新版PHP极大的增强功能和性能
Oct 09 PHP
php防注
Jan 15 PHP
通用PHP动态生成静态HTML网页的代码
Mar 04 PHP
php set_time_limit(0) 设置程序执行时间的函数
May 26 PHP
一个PHP缓存类代码(附详细说明)
Jun 09 PHP
php Smarty初体验二 获取配置信息
Aug 08 PHP
ThinkPHP实现多数据库连接的解决方法
Jul 01 PHP
封装ThinkPHP的一个文件上传方法实例
Oct 31 PHP
php按字符无乱码截取中文的方法
Mar 27 PHP
Yii统计不同类型邮箱数量的方法
Oct 18 PHP
PHP的RSA加密解密方法以及开发接口使用
Feb 11 PHP
laravel框架中表单请求类型和CSRF防护实例分析
Nov 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禁止页面缓存的代码
2011/10/23 PHP
在win7中搭建Linux+PHP 开发环境
2014/10/08 PHP
PHP设计模式之抽象工厂模式实例分析
2019/03/25 PHP
jquery form 加载数据示例
2014/04/21 Javascript
jquery的ajax跨域请求原理和示例
2014/05/08 Javascript
简单谈谈javascript代码复用模式
2015/01/28 Javascript
快速解决jquery.touchSwipe左右滑动和垂直滚动条冲突
2016/04/15 Javascript
用JavaScript动态建立或增加CSS样式表的实现方法
2016/05/20 Javascript
如何处理JSON中的特殊字符
2016/11/30 Javascript
详解Angular中的自定义服务Service、Provider以及Factory
2017/04/22 Javascript
js 只比较时间大小的实例
2017/10/26 Javascript
详解如何在项目中使用jest测试react native组件
2018/02/09 Javascript
vue 中filter的多种用法
2018/04/26 Javascript
vscode下的vue文件格式化问题
2018/11/28 Javascript
Vue3 中的数据侦测的实现
2019/10/09 Javascript
JavaScript数组排序小程序实现解析
2020/01/13 Javascript
Vue中多元素过渡特效的解决方案
2020/02/05 Javascript
package.json各个属性说明详解
2020/03/11 Javascript
JavaScript实现移动端带transition动画的轮播效果
2020/03/24 Javascript
python下载图片实现方法(超简单)
2017/07/21 Python
wtfPython—Python中一组有趣微妙的代码【收藏】
2018/08/31 Python
对python中词典的values值的修改或新增KEY详解
2019/01/20 Python
win8.1安装Python 2.7版环境图文详解
2019/07/01 Python
Python使用pyserial进行串口通信的实例
2019/07/02 Python
Python lxml模块的基本使用方法分析
2019/12/21 Python
python语言time库和datetime库基本使用详解
2020/12/25 Python
python 合并多个excel中同名的sheet
2021/01/22 Python
CheapTickets泰国:廉价航班,查看促销价格并预订机票
2019/12/28 全球购物
可靠的数据流传输TCP
2016/03/15 面试题
swtich是否能作用在byte上,是否能作用在long上,是否能作用在String上?
2013/03/30 面试题
详解如何解决使用JSON.stringify时遇到的循环引用问题
2021/03/23 Javascript
消防器材管理制度
2014/01/28 职场文书
排查整治工作方案
2014/06/09 职场文书
代理词怎么写
2015/05/25 职场文书
Python 类,对象,数据分类,函数参数传递详解
2021/09/25 Python
十大冰系宝可梦排名,颜值最高的阿罗拉九尾,第三使用率第一
2022/03/18 日漫