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 相关文章推荐
require(),include(),require_once()和include_once()的异同
Jan 02 PHP
php在线生成ico文件的代码
Oct 09 PHP
利用php+mysql来做一个功能强大的在线计算器
Oct 12 PHP
PHP设计模式之命令模式的深入解析
Jun 13 PHP
PHP查询网站的PR值
Oct 30 PHP
php数组去重实例及分析
Nov 26 PHP
php实例分享之通过递归实现删除目录下的所有文件详解
May 15 PHP
PHP中的一些常用函数收集
May 26 PHP
四个常见html网页乱码问题及解决办法
Sep 08 PHP
使用Composer安装Yii框架的方法
Mar 15 PHP
PHP  Yii清理缓存的实现方法
Nov 10 PHP
PHP 验证身份证是否合法的函数
Feb 09 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/10 PHP
PHP中文处理 中文字符串截取(mb_substr)和获取中文字符串字数
2011/11/10 PHP
PHP递归调用的小技巧讲解
2013/02/19 PHP
PHP下SSL加密解密、验证、签名方法(很简单)
2020/06/28 PHP
PHP浮点数的一个常见问题
2016/03/10 PHP
PHP基于接口技术实现简单的多态应用完整实例
2017/04/26 PHP
javascript call和apply方法
2008/11/24 Javascript
JavaScript 工具库 Cloudgamer JavaScript Library v0.1 发布
2009/10/29 Javascript
jquery.validate分组验证代码
2011/03/17 Javascript
jQuery中innerHeight()方法用法实例
2015/01/19 Javascript
JavaScript实现16进制颜色值转RGB的方法
2015/02/09 Javascript
JavaScript实现文字跟随鼠标特效
2015/08/06 Javascript
微信小程序 教程之条件渲染
2016/10/18 Javascript
利用JQuery直接调用asp.net后台的简单方法
2016/10/27 Javascript
javascript滚轮事件基础实例讲解(37)
2017/02/14 Javascript
微信小程序 action-sheet 反馈上拉菜单简单实例
2017/05/11 Javascript
Angularjs实现下拉框联动的示例代码
2017/08/22 Javascript
vuex中的 mapState,mapGetters,mapActions,mapMutations 的使用
2018/04/13 Javascript
jQuery+Datatables实现表格批量删除功能【推荐】
2018/10/24 jQuery
详解ES6中class的实现原理
2020/10/03 Javascript
[43:43]完美世界DOTA2联赛PWL S2 LBZS vs Forest 第三场 11.29
2020/12/02 DOTA
python脚本设置系统时间的两种方法
2016/02/21 Python
Python实现朴素贝叶斯的学习与分类过程解析
2019/08/24 Python
使用Python对Dicom文件进行读取与写入的实现
2020/04/20 Python
linux centos 7.x 安装 python3.x 替换 python2.x的过程解析
2020/12/14 Python
python爬虫破解字体加密案例详解
2021/03/02 Python
亚马逊西班牙购物网站:amazon西班牙
2017/03/06 全球购物
巴西最大的运动品牌:Olympikus
2020/07/14 全球购物
自主招生自荐信指南
2014/02/04 职场文书
公司成本主管岗位责任制
2014/02/21 职场文书
团委竞选演讲稿
2014/04/24 职场文书
街道党工委党的群众路线教育实践活动对照检查材料思想汇报
2014/10/05 职场文书
入党个人总结范文
2015/03/02 职场文书
Python基础之常用库常用方法整理
2021/04/30 Python
一篇文章带你搞懂Python类的相关知识
2021/05/20 Python
详细了解java监听器和过滤器
2021/07/09 Java/Android