首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

Yii2 整合 OAuth 擴展實現 QQ 互聯登錄完整教程

     編輯:PHP 綜合知識

前言

Yii2 官方提供 yii2-authclient 擴展,支援 OAuth1/OAuth2/OpenID 等多種認證協議,內建 Google、Facebook、Twitter、LinkedIn、GitHub 等客戶端。本文將詳細講解如何安裝配置該擴展,並自定義 QQ 互聯客戶端實現「一鍵 QQ 登錄」功能。

一、安裝 yii2-authclient

composer require --prefer-dist yiisoft/yii2-authclient "*"

二、基礎配置(以 Google、Facebook 為例)

編輯 config/main.php,在 components 下添加 authClientCollection:

'components' => [
    'authClientCollection' => [
        'class' => 'yii\authclient\Collection',
        'clients' => [
            'google' => [
                'class' => 'yii\authclient\clients\GoogleOpenId',
            ],
            'facebook' => [
                'class' => 'yii\authclient\clients\Facebook',
                'clientId' => 'your_facebook_app_id',
                'clientSecret' => 'your_facebook_app_secret',
            ],
        ],
    ],
    // ...
],

三、控制器處理回調

修改 controllers/SiteController.php,添加 auth 動作與成功回調:

use yii\authclient\AuthAction;

class SiteController extends Controller
{
    public function actions()
    {
        return [
            'auth' => [
                'class' => AuthAction::className(),
                'successCallback' => [$this, 'successCallback'],
            ],
        ];
    }

    public function successCallback($client)
    {
        $attributes = $client->getUserAttributes();
        // $attributes 包含:id、name、email 等用戶信息
        // 此處實現:綁定本地用戶、註冊新用戶、登錄、重定向等邏輯
    }
}

四、視圖中顯示登錄按鈕

 ['site/auth'],
]) ?>

五、核心難點:接入 QQ 互聯(OAuth2)

QQ 互聯的 OAuth2 實現與標準流程有細微差異:

  1. 獲取 access_token 後,需先調用 oauth2.0/me 獲取 openid。
  2. 攜帶 openid 與 oauth_consumer_key(即 AppID)調用 user/get_user_info 獲取用戶資料。
  3. 返回內容為 JSONP 格式(包裹在 callback(...) 中),非標準 JSON,導致框架默認解析失敗。

六、自定義 QQ OAuth2 客戶端組件

創建 common/components/QqOAuth.php:

scope === null) {
            $this->scope = implode(',', ['get_user_info']);
        }
    }

    protected function initUserAttributes()
    {
        // 1. 獲取 openid
        $openid = $this->api('oauth2.0/me', 'GET');
        // 2. 獲取用戶信息
        $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 返回的 JSONP 格式
     */
    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) {
                    // 關鍵:檢測並剝離 JSONP 回調包裹
                    if (strpos($rawResponse, "callback") !== false) {
                        $lpos = strpos($rawResponse, "(");
                        $rpos = strrpos($rawResponse, ")");
                        $rawResponse = substr($rawResponse, $lpos + 1, $rpos - $lpos - 1);
                        return $this->processResponse($rawResponse, self::CONTENT_TYPE_JSON);
                    }
                    throw new Exception('Unable to determine response content type automatically.');
                }
                return $this->processResponse($rawResponse, $contentType);

            case self::CONTENT_TYPE_JSON:
                $response = Json::decode($rawResponse, true);
                if (isset($response['error'])) {
                    throw new Exception('Response error: ' . $response['error']);
                }
                return $response;

            case self::CONTENT_TYPE_URLENCODED:
                $response = [];
                parse_str($rawResponse, $response);
                return $response;

            case self::CONTENT_TYPE_XML:
                return $this->convertXmlToArray($rawResponse);

            default:
                throw new Exception('Unknown response type "' . $contentType . '".');
        }
    }
}

七、註冊 QQ 客戶端

在 config/main.php 中添加:

'components' => [
    'authClientCollection' => [
        'class' => 'yii\authclient\Collection',
        'clients' => [
            'qq' => [
                'class' => 'common\components\QqOAuth',
                'clientId' => 'your_qq_app_id',
                'clientSecret' => 'your_qq_app_key',
            ],
        ],
    ],
],

八、視圖添加 QQ 登錄鏈接

使用 QQ 快速登錄

九、回調中區分不同客戶端

public function successCallback($client)
{
    $attributes = $client->getUserAttributes();
    if ($client->id === 'qq') {
        // QQ 專屬邏輯:$attributes['openid']、$attributes['nickname']、$attributes['figureurl_qq_2'] 等
    } elseif ($client->id === 'facebook') {
        // Facebook 邏輯
    }
    // 統一處理:綁定/註冊/登錄
}

總結

Yii2 的 authclient 架構清晰,擴展性強。接入 QQ 互聯的關鍵在於:理解其非標準 OAuth2 流程(需兩步獲取用戶信息)、處理 JSONP 響應格式。通過繼承 OAuth2 並重寫 initUserAttributes() 與 processResponse(),即可優雅地納入框架統一認證體系。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved