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 - Html Transfer Code
Oct 09 PHP
MySQL中create table语句的基本语法是
Jan 15 PHP
认识并使用PHP超级全局变量
Jan 26 PHP
php select,radio和checkbox默认选择的实现方法
May 15 PHP
zend optimizer在wamp的基础上安装图文教程
Oct 26 PHP
php+MySQL判断update语句是否执行成功的方法
Aug 28 PHP
php中常量DIRECTORY_SEPARATOR用法深入分析
Nov 14 PHP
帝国CMS留言板回复后发送EMAIL通知客户
Jul 06 PHP
PHP使用mkdir创建多级目录的方法
Dec 22 PHP
Yii 2.0中场景的使用教程
Jun 02 PHP
linux mint下安装phpstorm2020包括JDK部分的教程详解
Sep 17 PHP
php redis setnx分布式锁简单原理解析
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
PHP记录搜索引擎蜘蛛访问网站足迹的方法
2015/04/15 PHP
php基于PDO连接MSSQL示例DEMO
2016/07/13 PHP
基于php实现的php代码加密解密类完整实例
2016/10/12 PHP
php实现的简单中文验证码功能示例
2017/01/03 PHP
详解laravel passport OAuth2.0的4种模式
2019/11/04 PHP
弹出窗口并且此窗口带有半透明的遮罩层效果
2014/03/13 Javascript
jQuery插件slicebox实现3D动画图片轮播切换特效
2015/04/12 Javascript
微信支付如何实现内置浏览器的H5页面支付
2015/09/25 Javascript
jQuery 1.9.1源码分析系列(十)事件系统之绑定事件
2015/11/19 Javascript
AngularJS模块学习之Anchor Scroll
2016/01/19 Javascript
详解JavaScript权威指南之对象
2016/09/27 Javascript
浅谈javascript:两种注释,声明变量,定义函数
2016/10/05 Javascript
JavaScript实现多栏目切换效果
2016/12/12 Javascript
JavaScript表单验证的两种实现方法
2017/02/11 Javascript
响应式框架Bootstrap栅格系统的实例
2017/12/19 Javascript
vue.js element-ui tree树形控件改iview的方法
2018/03/29 Javascript
jQuery实现使用sort方法对json数据排序的方法
2018/04/17 jQuery
Vue父子组建的简单通信之控制开关Switch的实现
2018/06/04 Javascript
JS中的算法与数据结构之二叉查找树(Binary Sort Tree)实例详解
2019/08/16 Javascript
vue表单验证之禁止input输入框输入空格
2020/12/03 Vue.js
详解vue中使用transition和animation的实例代码
2020/12/12 Vue.js
ajax jquery实现页面某一个div的刷新效果
2021/03/04 jQuery
pip 错误unused-command-line-argument-hard-error-in-future解决办法
2014/06/01 Python
浅谈Python实现Apriori算法介绍
2017/12/20 Python
Python之多线程爬虫抓取网页图片的示例代码
2018/01/10 Python
Python转换itertools.chain对象为数组的方法
2020/02/07 Python
Django+boostrap 美化admin后台的操作
2020/03/11 Python
基于Python爬虫采集天气网实时信息
2020/06/05 Python
如何将anaconda安装配置的mmdetection环境离线拷贝到另一台电脑
2020/10/15 Python
绿化先进工作者事迹材料
2014/01/30 职场文书
护理中职生求职信范文
2014/02/24 职场文书
旅游与环境专业求职信
2014/06/05 职场文书
党员批评与自我批评发言材料
2014/10/14 职场文书
2019通用版导游词范本!
2019/08/07 职场文书
pycharm debug 断点调试心得分享
2021/04/16 Python
Go语言grpc和protobuf
2022/04/13 Golang