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 相关文章推荐
实用函数2
Nov 08 PHP
php+javascript的日历控件
Nov 19 PHP
php 缩略图实现函数代码
Jun 23 PHP
php中将数组存到文件里的实现代码
Jan 19 PHP
php实现爬取和分析知乎用户数据
Jan 26 PHP
PHP指定截取字符串中的中英文或数字字符的实例分享
Mar 18 PHP
PHP将URL转换成短网址的算法分享
Sep 13 PHP
Laravel使用memcached缓存对文章增删改查进行优化的方法
Oct 08 PHP
PHP命令Command模式用法实例分析
Aug 08 PHP
PHP实现的数据对象映射模式详解
Mar 20 PHP
PHP远程连接oracle数据库操作实现方法图文详解
Apr 11 PHP
使用SMB共享来绕过php远程文件包含的限制执行RFI的利用
May 31 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树的代码,可以嵌套任意层
2006/10/09 PHP
Php部分常见问题总结
2006/10/09 PHP
PHP生成随机密码方法汇总
2015/08/27 PHP
JQuery 写的个性导航菜单
2009/12/24 Javascript
jquery仿京东导航/仿淘宝商城左侧分类导航下拉菜单效果
2013/04/24 Javascript
Event altKey,ctrlKey,shiftKey属性解析
2013/12/18 Javascript
究竟什么是Node.js?Node.js有什么好处?
2015/05/29 Javascript
jquery实现图片平滑滚动详解
2017/03/22 jQuery
详解基于 axios 的 Vue 项目 http 请求优化
2017/09/04 Javascript
JavaScript实现打印星型金字塔功能实例分析
2017/09/27 Javascript
Echarts实现多条折线可拖拽效果
2019/12/19 Javascript
js实现多个标题吸顶效果
2020/01/08 Javascript
关于element-ui表单中限制输入纯数字的解决方式
2020/09/08 Javascript
vue+elementUI实现简单日历功能
2020/09/24 Javascript
vuejs实现下拉框菜单选择
2020/10/23 Javascript
python使用心得之获得github代码库列表
2014/06/25 Python
Python中的is和id用法分析
2015/01/26 Python
简单的Apache+FastCGI+Django配置指南
2015/07/22 Python
python去除文件中空格、Tab及回车的方法
2016/04/12 Python
Python使用getpass库读取密码的示例
2017/10/10 Python
python爬取亚马逊书籍信息代码分享
2017/12/09 Python
django Serializer序列化使用方法详解
2018/10/16 Python
Python requests模块实例用法
2019/02/11 Python
通过PHP与Python代码对比的语法差异详解
2019/07/10 Python
python numpy 矩阵堆叠实例
2020/01/17 Python
python使用Thread的setDaemon启动后台线程教程
2020/04/25 Python
python 实现单例模式的5种方法
2020/09/23 Python
详解px单位html5响应式方案
2018/03/08 HTML / CSS
canvas绘制太极图的实现示例
2020/04/29 HTML / CSS
计算s=f(f(-1.4))的值
2014/05/06 面试题
助残日活动总结
2014/08/27 职场文书
政风行风评议整改方案
2014/09/15 职场文书
给老师的感谢信
2015/01/20 职场文书
优秀教师个人总结
2015/02/11 职场文书
农民工工资承诺书大全
2015/05/04 职场文书
pytorch中的torch.nn.Conv2d()函数图文详解
2022/02/28 Python