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 相关文章推荐
在PHP3中实现SESSION的功能(一)
Oct 09 PHP
扩展你的 PHP 之入门篇
Dec 04 PHP
php中static静态变量的使用方法详解
Jun 04 PHP
php采集时被封ip的解决方法
Aug 29 PHP
php产生随机数的两种方法实例代码 输出随机IP
Apr 08 PHP
解析php中用PHPMailer来发送邮件的示例(126.com的例子)
Jun 24 PHP
PHP+jquery实时显示网站在线人数的方法
Jan 04 PHP
YII Framework框架教程之国际化实现方法
Mar 14 PHP
深入解析PHP的Yii框架中的缓存功能
Mar 29 PHP
Yii2使用$this-&gt;context获取当前的Module、Controller(控制器)、Action等
Mar 29 PHP
基于swoole实现多人聊天室
Jun 14 PHP
Swoole 5将移除自动添加Event::wait()特性详解
Jul 10 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
967 个函式
2006/10/09 PHP
PHP Warning: PHP Startup: Unable to load dynamic library \ D:/php5/ext/php_mysqli.dll\
2012/06/17 PHP
PHP字符串比较函数strcmp()和strcasecmp()使用总结
2014/11/19 PHP
微信公众平台开发教程⑤ 微信扫码支付模式介绍
2019/04/10 PHP
推荐40个非常优秀的jQuery插件和教程【系列三】
2011/11/09 Javascript
JSON.stringify 语法实例讲解
2012/03/14 Javascript
多种方式实现JS调用后台方法进行数据交互
2013/08/20 Javascript
JavaScript/Js脚本处理html元素的自定义属性解析(亲测兼容Firefox与IE)
2013/11/25 Javascript
javascript面向对象之this关键词用法分析
2015/01/13 Javascript
Jquery实现动态切换图片的方法
2015/05/18 Javascript
js实现文本框只允许输入数字并限制数字大小的方法
2015/08/19 Javascript
AngularJS中$interval的用法详解
2016/02/02 Javascript
js动态添加的DIV中的onclick事件简单实例
2016/07/25 Javascript
js模式化窗口问题![window.dialogArguments]
2016/10/30 Javascript
js字符串与Unicode编码互相转换
2017/05/17 Javascript
基于react组件之间的参数传递(详解)
2017/09/05 Javascript
使用 Vue 绑定单个或多个 Class 名的实例代码
2018/01/08 Javascript
JS数组及对象遍历方法代码汇总
2020/06/16 Javascript
Nuxt.js nuxt-link与router-link的区别说明
2020/11/06 Javascript
js实现移动端轮播图滑动切换
2020/12/21 Javascript
[41:05]Serenity vs Pain 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
解决PyCharm中光标变粗的问题
2017/08/05 Python
python 猴子补丁(monkey patch)
2019/06/26 Python
用django设置session过期时间的方法解析
2019/08/05 Python
Python3+Requests+Excel完整接口自动化测试框架的实现
2019/10/11 Python
HTML5的语法变化介绍
2013/08/13 HTML / CSS
HTML5 embed标签定义和用法详解
2014/05/09 HTML / CSS
浅析HTML5:'data-'属性的作用
2018/01/23 HTML / CSS
LG西班牙网上商店:Tienda LG Online Es
2019/07/30 全球购物
美体小铺印度官网:The Body Shop印度
2019/10/17 全球购物
历史教育专业个人求职信
2013/12/13 职场文书
餐厅经理岗位职责和岗位目标
2014/02/13 职场文书
初中军训感想300字
2014/03/05 职场文书
吨的认识教学反思
2014/04/27 职场文书
2014年村官工作总结
2014/11/24 职场文书
病人写给医生的感谢信
2015/01/23 职场文书