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+MySQL的聊天室设计
Oct 09 PHP
PHP生成静态页面详解
Nov 19 PHP
小偷PHP+Html+缓存
Dec 20 PHP
UTF8编码内的繁简转换的PHP类
Jul 09 PHP
php ajax 静态分页过程形式
Sep 02 PHP
php中判断数组是一维,二维,还是多维的解决方法
May 04 PHP
php变量作用域的深入解析
Jun 03 PHP
php+js实现百度地图多点标注的方法
Nov 30 PHP
php利用imagemagick实现复古老照片效果实例
Feb 16 PHP
PHP实现的超长文本分页显示功能示例
Jun 04 PHP
PHP实现redis限制单ip、单用户的访问次数功能示例
Jun 16 PHP
PHP simplexml_import_dom()函数讲解
Feb 03 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/01/06 PHP
PHP5中新增stdClass 内部保留类
2011/06/13 PHP
自定义min版smarty模板引擎MinSmarty.class.php文件及用法
2016/05/20 PHP
PHP请求Socket接口测试实例
2016/08/12 PHP
php 实现一个字符串加密解密的函数实例代码
2016/11/01 PHP
PHP实现删除多重数组对象属性并重新赋值的方法
2017/06/07 PHP
php 的多进程操作实践案例分析
2020/02/28 PHP
javascript hasFocus使用实例
2010/06/29 Javascript
js的hasownproperty使用示例
2014/03/02 Javascript
Jquery动态添加及删除页面节点元素示例代码
2014/06/16 Javascript
jQuery实现的感应鼠标悬停图片色彩渐显效果
2015/03/03 Javascript
基于javascript实现漂亮的页面过渡动画效果附源码下载
2015/10/26 Javascript
JS组件Form表单验证神器BootstrapValidator
2016/01/26 Javascript
更高效的使用JQuery 这里总结了8个小技巧
2016/04/13 Javascript
less简单入门(CSS 预处理语言)
2017/03/08 Javascript
使用watch监听路由变化和watch监听对象的实例
2018/02/24 Javascript
解决vue项目报错webpackJsonp is not defined问题
2018/03/14 Javascript
通过webpack引入第三方库的方法
2018/07/20 Javascript
layer弹出层自定义提交取消按钮的例子
2019/09/10 Javascript
基于layui的table插件进行复选框联动功能的实现方法
2019/09/19 Javascript
RxJS在TypeScript中的简单使用详解
2020/04/13 Javascript
[02:47]DOTA2亚洲邀请赛 HR战队出场宣传片
2015/02/07 DOTA
Python使用迭代器打印螺旋矩阵的思路及代码示例
2016/07/02 Python
Python增量循环删除MySQL表数据的方法
2016/09/23 Python
Python3获取拉勾网招聘信息的方法实例
2019/04/03 Python
详解pandas删除缺失数据(pd.dropna()方法)
2019/06/25 Python
django之从html页面表单获取输入的数据实例
2020/03/16 Python
Python迭代器Iterable判断方法解析
2020/03/16 Python
python中 _、__、__xx__()区别及使用场景
2020/06/30 Python
纯CSS3单页切换导航菜单界面设计的简单实现
2016/08/16 HTML / CSS
HTML5学习笔记之History API
2015/02/26 HTML / CSS
HTML+CSS+JavaScript实现图片3D展览的示例代码
2020/10/12 HTML / CSS
销售助理岗位职责
2014/02/21 职场文书
终止合同协议书
2014/04/17 职场文书
Python控制台输出俄罗斯方块的方法实例
2021/04/17 Python
Node实现搜索框进行模糊查询
2021/06/28 Javascript