使用 Laravel Socialite 集成微信登錄

rabow 8年前發布 | 24K 次閱讀 Laravel Web框架

Laravel Socialite

Laravel Socialite provides an expressive, fluent interface to OAuth authentication with 非死book, 推ter, Google, LinkedIn, GitHub and Bitbucket. It handles almost all of the boilerplate social authentication code you are dreading writing.

Laravel Socialite 為第三方應用的 OAuth 認證提供了非常豐富友好的接口,我們使用它可以非常方便快捷的對類似微信、微博等第三方登錄進行集成。

Open Authorization

OAuth(開放授權)是一個開放標準,允許用戶讓第三方應用訪問該用戶在某一網站上存儲的私密的資源(如照片,視頻,聯系人列表),而無需將用戶名和密碼提供給第三方應用。

OAuth 允許用戶提供一個令牌,而不是用戶名和密碼來訪問他們存放在特定服務提供者的數據。每一個令牌授權一個特定的網站(例如,視頻編輯網站)在特定的時段(例如,接下來的 2 小時內)內訪問特定的資源(例如僅僅是某一相冊中的視頻)。這樣,OAuth 讓用戶可以授權第三方網站訪問他們存儲在另外服務提供者的某些特定信息,而非所有內容。

我們的應用與使用 OAuth 標準的第三方應用的交互流程一般是這樣的:

  • 展示跳轉到第三方應用登錄的鏈接
  • 用戶點擊鏈接跳轉到第三方應用登錄并進行授權
  • 在用戶授權后第三方應用會跳轉到我們所指定的應用回調資源地址并伴隨用于交互 AccessToken 的 Code
  • 我們的應用拿到 Code 后自主請求第三方應用并使用 Code 獲取該用戶的 AccessToken
  • 獲取 AccessToken 之后的應用即可自主的從第三方應用中獲取用戶的資源信息

Laravel Socialite UML

Socialite

安裝 Laravel Socialite

使用 Composer 進行安裝:

composer require laravel/socialite

配置

你需要在 config/app.php 的 providers 鍵中追加:

'providers' => [
    // Other service providers...

Laravel\Socialite\SocialiteServiceProvider::class,

],</code></pre>

在 aliasses 鍵中添加 Socialite :

'Socialite' => Laravel\Socialite\Facades\Socialite::class,

在 config/services.php 配置文件中添加驅動器配置項:

'github' => [
    'client_id' => 'your-github-app-id',
    'client_secret' => 'your-github-app-secret',
    'redirect' => 'http://your-callback-url',
],

至此整個流程安裝完畢。

集成微信登錄

集成微信我們需要提供一個 WechatServiceProvider 和 一個 WechatProvider ,用這兩個文件來為微信登錄提供驅動,Laravel Socialite 的 SocialiteManager 繼承自 Illuminate\Support\Manager 類,而其對自定義驅動提供了友好的接口支持,所以我們可以手動的添加一個 Wechat 驅動器:

<?php

namespace Crowdfunding\Providers\Socialite;

use Laravel\Socialite\Two\AbstractProvider; use Laravel\Socialite\Contracts\Provider as ProviderInterface; use Laravel\Socialite\Two\User; use GuzzleHttp\ClientInterface;

class WechatProvider extends AbstractProvider implements ProviderInterface { /**

* openid for get user.
* @var string
*/
protected $openId;

/**
 * set Open Id.
 *
 * @param  string  $openId
 */
public function setOpenId($openId) {
    $this->openId = $openId;

    return $this;
}

/**
 * {@inheritdoc}.
 */
protected $scopes = ['snsapi_login'];

/**
 * {@inheritdoc}.
 */
public function getAuthUrl($state)
{
    return $this->buildAuthUrlFromBase('https://open.weixin.qq.com/connect/qrconnect', $state);
}

/**
 * {@inheritdoc}.
 */
protected function buildAuthUrlFromBase($url, $state)
{
    $query = http_build_query($this->getCodeFields($state), '', '&', $this->encodingType);

    return $url.'?'.$query.'#wechat_redirect';
}

/**
 * {@inheritdoc}.
 */
protected function getCodeFields($state = null)
{
    return [
        'appid'         => $this->clientId, 'redirect_uri' => $this->redirectUrl,
        'response_type' => 'code', 'scope'                 => $this->formatScopes($this->scopes, $this->scopeSeparator),
        'state'         => $state,
    ];
}

/**
 * {@inheritdoc}.
 */
public function getTokenUrl()
{
    return 'https://api.weixin.qq.com/sns/oauth2/access_token';
}

/**
 * {@inheritdoc}.
 */
public function getUserByToken($token)
{
    $response = $this->getHttpClient()->get('https://api.weixin.qq.com/sns/userinfo', [
        'query' => [
            'access_token' => $token,
            'openid'       => $this->openId,
            'lang'         => 'zh_CN',
        ],
    ]);

    return json_decode($response->getBody(), true);

}

/**
 * {@inheritdoc}.
 */
public function mapUserToObject(array $user)
{
    return (new User())->setRaw($user)->map([
      'openid' => $user['openid'], 'nickname' => $user['nickname'],
      'avatar' => $user['headimgurl'], 'name' => $user['nickname'],
      'email'  => null, 'unionid'             => $user['unionid']
    ]);
}

/**
* {@inheritdoc}.
*/
protected function getTokenFields($code)
{
    return [
        'appid' => $this->clientId, 'secret' => $this->clientSecret,
        'code' => $code, 'grant_type' => 'authorization_code',
    ];
}

/**
* {@inheritdoc}.
*/
public function getAccessTokenResponse($code)
{
    $postKey = (version_compare(ClientInterface::VERSION, '6') === 1) ? 'form_params' : 'body';

    $response = $this->getHttpClient()->post($this->getTokenUrl(), [
        'headers' => ['Accept' => 'application/json'],
        $postKey => $this->getTokenFields($code),
    ]);

    $responseBody = json_decode($response->getBody(), true);
    $this->setOpenId($responseBody['openid']);

    return $responseBody;
}

}</code></pre>

編寫完驅動之后我們需要注冊該驅動器到 SocialiteManager 中,因此我們編寫一個 WechatServiceProvider:

<?php

namespace Crowdfunding\Providers\Socialite;

use Illuminate\Support\ServiceProvider;

class WechatServiceProvider extends ServiceProvider { public function boot() { $this->app->make('Laravel\Socialite\Contracts\Factory')->extend('wechat', function ($app) { $config = $app['config']['services.wechat']; return new WechatProvider( $app['request'], $config['client_id'], $config['client_secret'], $config['redirect'] ); }); } public function register() {

}

}</code></pre>

接著我們就可以添加配置項及將服務提供者注冊到 Laravel 中:

// app.php
'providers' => [
    // Other service providers...
    Crowdfunding\Providers\Socialite\WechatServiceProvider::class,
],

// services.php 'wechat' => [ 'client_id' => 'appid', 'client_secret' => 'appSecret', 'redirect' => '緊接著添加路由及控制器:

// route.php
Route::group(['middleware' => 'web'], function () {
    Route::get('oauth/callback/driver/{driver}', 'OAuthAuthorizationController@handleProviderCallback');
    Route::get('oauth/redirect/driver/{driver}', 'OauthAuthorizationController@redirectToProvider');
});

控制器:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests; use Socialite;

class OAuthAuthorizationController extends Controller { // public function redirectToProvider($driver) { return Socialite::driver($driver)->redirect(); }

public function handleProviderCallback($driver) {
    $user =  Socialite::driver($driver)->user();
    // dd($user)
}

}</code></pre>

至此集成完畢。

 

來自:http://www.jianshu.com/p/1e16beb46ea3

 

 本文由用戶 rabow 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!