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 相关文章推荐
第1次亲密接触PHP5(1)
Oct 09 PHP
php include的妙用,实现路径加密
Jul 29 PHP
php 删除无限级目录与文件代码共享
Nov 22 PHP
PHP获取类中常量,属性,及方法列表的方法
Apr 09 PHP
PHP 简单日历实现代码
Oct 28 PHP
PHP处理SQL脚本文件导入到MySQL的代码实例
Mar 17 PHP
PHP多进程编程实例
Oct 15 PHP
php下foreach提示Warning:Invalid argument supplied for foreach()的解决方法
Nov 11 PHP
php制作的简单验证码识别代码
Jan 26 PHP
PHP开发中常用的十个代码样例
Feb 02 PHP
PHP框架Laravel插件Pagination实现自定义分页
Apr 22 PHP
PHP+redis实现的悲观锁机制示例
Jun 12 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中使用explode查找某个字符是否存在的方法
2011/07/12 PHP
php查看请求头信息获取远程图片大小的方法分享
2013/12/25 PHP
PHP之APC缓存详细介绍 apc模块安装
2014/01/13 PHP
php中require和require_once的区别说明
2014/02/27 PHP
php 使用GD库为页面增加水印示例代码
2014/03/24 PHP
PHP图像处理之使用imagecolorallocate()函数设置颜色例子
2014/11/19 PHP
php下Memcached入门实例解析
2015/01/05 PHP
php文件上传你必须知道的几点
2015/10/20 PHP
php无限分类使用concat如何实现
2015/11/05 PHP
浅谈Yii乐观锁的使用及原理
2017/07/25 PHP
PHP使用redis位图bitMap 实现签到功能
2019/10/08 PHP
获取dom元素那些讨厌的位置封装代码
2010/06/23 Javascript
可选择和输入的下拉列表框示例
2013/11/05 Javascript
浅谈JavaScript function函数种类
2014/12/29 Javascript
JQuery判断checkbox是否选中及其它复选框操作方法合集
2015/06/01 Javascript
jquery UI Datepicker时间控件的使用方法(加强版)
2015/11/07 Javascript
jQuery 1.9.1源码分析系列(十四)之常用jQuery工具
2015/12/02 Javascript
window.onload绑定多个事件的两种解决方案
2016/05/15 Javascript
jQuery绑定自定义事件的魔法升级版
2016/06/30 Javascript
JavaScript中无法通过div.style.left获取值的解决方法
2017/02/19 Javascript
jQuery动画_动力节点节点Java学院整理
2017/07/04 jQuery
利用Node.js检测端口是否被占用的方法
2017/12/07 Javascript
Vue 页面跳转不用router-link的实现代码
2018/04/12 Javascript
Vuex实现数据共享的方法
2019/12/20 Javascript
原生js实现俄罗斯方块
2020/10/20 Javascript
python web.py开发httpserver解决跨域问题实例解析
2018/02/12 Python
python使用循环打印所有三位数水仙花数的实例
2018/11/13 Python
利用Python查看微信共同好友功能的实现代码
2019/04/24 Python
如何基于python对接钉钉并获取access_token
2020/04/21 Python
Django模型验证器介绍与源码分析
2020/09/08 Python
python中字符串的编码与解码详析
2020/12/03 Python
微软香港官网及网上商店:Microsoft HK
2016/09/01 全球购物
会计专业应届生自荐信
2014/02/07 职场文书
运动会开幕式主持词
2014/03/28 职场文书
追讨欠款律师函
2015/05/27 职场文书
python读取并查看npz/npy文件数据以及数据显示方法
2022/04/14 Python