淺談多個社交賬號的綁定設計

Dearmadman 在 Laravel Socialite 詳解 中使用 larastarscn/socialite 解決了第三方賬號登錄集成的問題,那么在獲取到用戶資料之后呢?集成多個社交賬號,該如何綁定同一個賬號?本篇就讓我們來探討一下集成登錄的那點事。

起初

起初,當我們只需要集成單個社交登錄時,我們可能會為了快速的完成任務簡單粗暴的在用戶模型中加入 open_id 或者 github_id 類似的屬性,那么在數(shù)據(jù)庫中,我們需要在表中添加相應的字段。這是可以快速有效的完成任務的做法。

但是,當更多的需求來臨時,要求我們額外的集成一種或者多種社交登錄,那該怎么辦?難道我們還要任性的在表結(jié)構(gòu)中添加相應的字段?

Schema::table('users', function ($table) {
  $table->string('github_id');
  $table->string('douban_id');
});

這很明顯的違背了開放封閉原則,假如我們這么做,那么可以想象的當每多集成一種登錄時,我們就需要對數(shù)據(jù)表結(jié)構(gòu)做出一次修正,并且,在登錄授權(quán)回調(diào)驗證時,還要增加一道集成驅(qū)動與字段查詢匹配的工序。

那應該怎么做?

設想

這么想來,User 表是否承擔了過多的能力,它是否應該浪費自己的精力來管理這些社交標識?那不如我們安排 SocialiteUser 來專門管理用戶與社交賬號之間的關(guān)系?我們需要設計一種易擴展的方案來管理不同驅(qū)動的社交登錄,那么我們很容易的設計出這種表結(jié)構(gòu):

- socialite_users
  - id
  - user_id
  - driver
  - open_id

SocialiteUser 應該具有哪些職責?很顯然,它主要用來維護社交登錄標識和用戶模型之間的關(guān)系。那么它應該具有以下能力:

  • 將社交登錄賬戶綁定到用戶模型上
  • 獲取匹配的用戶模型

以下為簡單的代碼演示:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class SocialiteUser extends Model
{
    public $guarded = ['id'];

    /**
     * Get user instance by driver and openid.
     *
     * @param  $driver  string
     * @param  $openid  string
     * @return /App/User|null
     */
    public function getUser($driver, $openid)
    {
        $finder =  $this->where([
            'driver' => $driver,
            'open_id' => $openid
        ])->first();

        return $finder ? $finder->user : $finder;
    }

    /**
     * get related user model.
     *
     * @return /App/User||null
     */
    public function user()
    {
        return $this->belongsTo('App\User');
    }

    /**
     * Save a new record.
     *
     * @param  $userId  integer
     * @param  $driver  string
     * @param  $id  string
     * @return /App/SocialiteUser
     */
    public function saveOne($userId, $driver, $id)
    {
        return $this->create([
            'user_id' => $userId,
            'driver' => $driver,
            'open_id' => $id
       ]);
    }
}

使用

在授權(quán)登錄流程中,用戶同意授權(quán),第三方應用將重定向到回調(diào)路由,回調(diào)路由中 Socialite 會主動請求獲取用戶資料,并將用戶的社交標識 ID 映射到 User 模型的 id 屬性上。

那么我們就可以在回調(diào)路由中根據(jù)驅(qū)動標識和用戶相應的社交標識 ID 來匹配查詢庫中是否已存在綁定的用戶。如果存在那就直接使用匹配到的用戶登錄,如果不存在,那么就生成一個用戶,并為這個用戶附加社交賬戶信息。然后使用新生成的賬戶登錄。

<?php

namespace App\Http\Controllers;

use App\SocialiteUser;
use App\User;
use Socialite;

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

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

        $model = new User();
        $socialiteUser = new SocialiteUser();
        $finder = $socialiteUser->getUser($driver, $user->id);
        if (! $finder) {
            $finder = $model->generateUserInstance();
            $finder->save();
            $socialiteUser->saveOne($finder->id, $driver, $user->id);
        }
        
        Auth::login($finder);

        return view('home');
    }
}

這樣看來,如果需求一種新的社交登錄的集成,那么完全不需要做出其它代碼的改動,直接配置驅(qū)動就可以了。

PS: 歡迎關(guān)注簡書 Laravel 專題,也歡迎 Laravel 相關(guān)文章的投稿 :),作者知識技能水平有限,如果你有更好的設計方案歡迎討論交流,如果有錯誤的地方也請批評指正,在此表示感謝謝謝 :)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

  • 原文鏈接 必備品 文檔:Documentation API:API Reference 視頻:Laracasts ...
    layjoy閱讀 8,719評論 0 121
  • 點擊查看原文 Web SDK 開發(fā)手冊 SDK 概述 網(wǎng)易云信 SDK 為 Web 應用提供一個完善的 IM 系統(tǒng)...
    layjoy閱讀 14,354評論 0 15
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,319評論 25 708
  • 社交紅利閱讀筆記 書名:社交紅利(修訂升級版) 作者:徐志斌 出版社:中信出版社 正文前筆記: 推薦序1摘要 社交...
    鳧水閱讀 9,423評論 4 26
  • 都是第一次做人,我憑什么讓你? 01 我閨蜜簡直想動手殺了室友。 有天晚上回宿舍,她發(fā)現(xiàn)自己的化妝品、耳環(huán)、衣服灑...
    南巷故人safe閱讀 282評論 0 0

友情鏈接更多精彩內(nèi)容