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自定义函数返回多个值
Nov 26 PHP
创建数据库php代码 用PHP写出自己的BLOG系统
Apr 12 PHP
Apache2中实现多网站域名绑定的实现方法
Jun 01 PHP
Uncaught exception com_exception with message Failed to create COM object
Jan 11 PHP
介绍一些PHP判断变量的函数
Apr 24 PHP
探讨:array2xml和xml2array以及xml与array的互相转化
Jun 24 PHP
完美解决PHP中的Cannot modify header information 问题
Aug 12 PHP
yii框架配置默认controller和action示例
Apr 30 PHP
PHP抓取网页、解析HTML常用的方法总结
Jul 01 PHP
php获取指定(访客)IP所有信息(地址、邮政编码、国家、经纬度等)的方法
Jul 06 PHP
在Mac OS上自行编译安装Apache服务器和PHP解释器
Dec 24 PHP
php双层循环(九九乘法表)
Oct 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
水质对咖图啡风味的影响具体有哪些
2021/03/03 冲泡冲煮
php一维二维数组键排序方法实例总结
2014/11/13 PHP
PHP MVC框架路由学习笔记
2016/03/02 PHP
PHP屏蔽关键字实现方法
2016/11/17 PHP
自用js开发框架小成 学习js的朋友可以看看
2010/11/16 Javascript
Javascript表格翻页效果的具体实现
2013/10/05 Javascript
jquery基础教程之数组使用详解
2014/03/10 Javascript
javascript中SetInterval与setTimeout的定时器用法
2015/08/24 Javascript
javascript时间差插件分享
2016/07/18 Javascript
基于bootstrap实现收缩导航条
2017/03/17 Javascript
JavaScript运动框架 链式运动到完美运动(五)
2017/05/18 Javascript
Webpack如何引入bootstrap的方法
2017/06/17 Javascript
javascript基于定时器实现进度条功能实例
2017/10/13 Javascript
JavaScript常用工具方法封装
2019/02/12 Javascript
vue elementui 实现搜索栏公共组件封装的实例代码
2020/01/20 Javascript
node创建Vue项目步骤详解
2020/03/06 Javascript
[46:43]DOTA2上海特级锦标赛D组小组赛#1 EG VS COL第三局
2016/02/28 DOTA
Python urls.py的三种配置写法实例详解
2017/04/28 Python
pip install urllib2不能安装的解决方法
2018/06/12 Python
django项目中新增app的2种实现方法
2020/04/01 Python
css3弹性盒模型(Flexbox)详细介绍
2014/10/08 HTML / CSS
英国钻石公司:British Diamond Company
2020/02/16 全球购物
Java基础面试题
2012/11/02 面试题
土木工程专业大学毕业生求职信
2013/10/13 职场文书
政府法律服务方案
2014/06/14 职场文书
群众路线个人剖析材料
2014/10/07 职场文书
校运动会广播稿300字
2014/10/07 职场文书
银行业务授权委托书
2014/10/10 职场文书
财政局长个人总结
2015/03/04 职场文书
2015年大学生党员承诺书
2015/04/27 职场文书
自书遗嘱范文
2015/08/07 职场文书
小学生禁毒教育心得体会
2016/01/15 职场文书
导游词创作书写原则以及开场白技巧怎么学?
2019/09/25 职场文书
导游词之蜀山胜景瓦屋山
2019/11/29 职场文书
Python制作一个随机抽奖小工具的实现
2021/07/07 Python
浅谈MySQL表空间回收的正确姿势
2021/10/05 MySQL