摘要:這樣,讓用戶可以授權第三方網站訪問他們存儲在另外服務提供者的某些特定信息,而非所有內容。
不久之前 Dearmadman 曾寫過一篇 使用 Laravel Socialite 集成微信登錄 的文章,但是似乎還是有些同學不太明白,詢問著如何集成 QQ 登錄,那么,本篇我們就來剖析一下 Laravel Socialite 的詳細內容。讓各位同學都獲得 Laravel Socialite 所提供的驅動適配能力。
Laravel SocialiteLaravel Socialite 為第三方應用的 OAuth 認證提供了非常豐富友好的接口,我們使用它可以非常方便快捷的對類似微信、微博等第三方登錄進行集成。
那么首先,你需要知道 Laravel Socialite 主要是用于那些 OAuth 授權登錄的。這些場景下的第三方應用比如微信,QQ,微博等,都使用了 OAuth 協議為用戶提供授權其它應用獲取用戶信息及權限的能力。
Open AuthorizationOAuth(開放授權)是一個開放標準,允許用戶讓第三方應用訪問該用戶在某一網站上存儲的私密的資源(如照片,視頻,聯系人列表),而無需將用戶名和密碼提供給第三方應用。
OAuth 允許用戶提供一個令牌,而不是用戶名和密碼來訪問他們存放在特定服務提供者的數據。每一個令牌授權一個特定的網站(例如,視頻編輯網站)在特定的時段(例如,接下來的 2 小時內)內訪問特定的資源(例如僅僅是某一相冊中的視頻)。這樣,OAuth 讓用戶可以授權第三方網站訪問他們存儲在另外服務提供者的某些特定信息,而非所有內容。
我們的應用與使用 OAuth 標準的第三方應用的交互流程一般是這樣的:
展示跳轉到第三方應用登錄的鏈接
用戶點擊鏈接跳轉到第三方應用登錄并進行授權
在用戶授權后第三方應用會跳轉到我們所指定的應用回調資源地址并伴隨用于交互 AccessToken 的 Code
我們的應用拿到 Code 后自主請求第三方應用并使用 Code 獲取該用戶的 AccessToken
獲取 AccessToken 之后的應用即可自主的從第三方應用中獲取用戶的資源信息
詳解對于以上流程,我們來分析一下 Laravel Socialite 針對上面的每一步都做了些什么,我們將構建一個 QQProvider 來作為演示示例:
第三方應用的登錄鏈接顯而易見的,第一步我們需要構建用于跳轉到第三方登錄的 URL,這里需要提供一些額外的參數來進行應用的識別,比如,當你為你的應用注冊 QQ 登錄網站接入應用時,QQ 互聯會為你提供一組數據用來驗證登錄來源的合法性,通常這些關鍵數據為以下幾項:
{ appid: "xxxxxxxxx", app_secret: "xxxxxxxxx", redirect: "xxxxxxxxxxx" }
在 Laravel Socialite 中這些關鍵數據映射到了 AbstractProvider 頂級抽象中,你可以將這些配置項定義到 services.php 配置文件中:
"qq" => [ "client_id" => "your-qq-app-id", "client_secret" => "your-qq-app-secret", "redirect" => "http://your-callback-url", ],
我們將會在后續注冊擴展驅動時使用這些配置。
如果需要為第三方應用登錄構建自定義的驅動,那么你需要先繼承 AbstractProvider,并且實現 ProviderInterface 接口,因為國內流行的應用都使用的 OAuth 2.0 協議,比如 QQ,就是使用的這種協議,所以我們需要繼承 LaravelSocialiteTwoAbstractProvider 抽象類,并且實現 ProviderInterface 接口。
ProviderInterface 接口限定了兩個方法: redirect 和 user,其中 redirect 方法就是返回構建后的跳轉響應,用于跳轉到第三方應用進行授權登錄,而 user 方法就是用來在用戶同意授權登錄之后,獲取第三方應用中用戶的信息數據的。這些方法已經在 AbstractProvider 抽象類中提供了實現。所以基本上你不需要再去實現它。
Socialite 通過三個函數的配合來構造跳轉 URL,它們分別是 getAuthUrl,buildAuthUrlFromBase 和 getCodeFields:
getAuthUrl($state): 返回構造完成后的跳轉 URL,它需要調用 BuildAuthUrlFromBase 函數,我們只需要在這里指定第三方應用所規定的應用登錄授權的地址即可。
BuildAuthUrlFromBase($url, $state): 它主要是為授權地址構建相應的查詢參數,將驅動配置中的關鍵數據以及第三方應用所規定的數據填充到 URL 中。在它的內部需要調用 getCodeFields 函數,我們只需要在這里返回第三方應用所規定的應用登錄授權的地址與查詢參數合并即可。
getCodeFields($state = null): 將驅動配置信息映射到第三方應用登錄驗證所需的參數中。
使用 Code 換取 AccessToken當用戶同意登錄授權之后,第三方應用會將地址跳轉到 redirect 所配置的地址中,并攜帶 code 參數,你需要使用 code 來換取 access_token。然后使用 access_token 換取用戶的信息數據。這就是集成登錄的整個流程。
AbstractProvider 中已經為 user 方法提供了基本的實現,并且它將經常變化的部分提取到了其它的方法中,這樣我們在開發新驅動的時候,基本不需要重寫 user 方法。我們來看一些為了完成這些操作,我們需要用到哪些方法。
首先,在登錄回調的路由中,我們會獲得請求中攜帶的 code 參數,然后需要使用 code 來換取 access_token,我們先來看一下底層 AbstractProvider 中 user 的實現:
/** * {@inheritdoc} */ public function user() { if ($this->hasInvalidState()) { throw new InvalidStateException; } $response = $this->getAccessTokenResponse($this->getCode()); $user = $this->mapUserToObject($this->getUserByToken( $token = Arr::get($response, "access_token") )); return $user->setToken($token) ->setRefreshToken(Arr::get($response, "refresh_token")) ->setExpiresIn(Arr::get($response, "expires_in")); }
其中用到的關鍵方法有:
getAccessTokenResponse($code): 它需要使用 code 來換取 access_token 響應的主體,它應該返回一個包含了 access_token 的數組。根據不同應用所規定的響應格式,你可能會需要在這里做出一些適配,那么,在集成自定義驅動時,重寫這個方法就可以了。
getUserByToken($token): 使用 access_token 向第三方應用獲取用戶的數據。它應該返回一個數組。
mapUserToObject(array $user): 它應該在使用 access_token 換取用戶數據之后,將用戶數據數組存儲到 LaravelSocialiteTwoUser 實例中的 user 屬性中,并將相應的數據映射到實例的屬性。
所以流程上也就很清晰了,那么擴展自定義的驅動也就很簡單了,調用 getAccessTokenResponse 方法時,需要指定換取 token 的 URL,所以我們需要重寫 getTokenUrl 方法:
/** * {@inheritdoc}. */ public function getTokenUrl() { return "https://graph.qq.com/oauth2.0/token"; }
在構建換取 token 的 URL 時,還要組合相應的參數,所以我們需要重寫 getTokenFields 方法:
/** * {@inheritdoc}. */ protected function getTokenFields($code) { return [ "client_id" => $this->clientId, "client_secret" => $this->clientSecret, "code" => $code, "grant_type" => "authorization_code", "redirect_uri" => $this->redirectUrl, ]; }
然后,在 getUserByToken 方法中完成使用 token 換取用戶數據的業務邏輯就可以了,它應該返回一個數組:
/** * {@inheritdoc}. */ public function getUserByToken($token) { $response = $this->getHttpClient()->get("https://graph.qq.com/oauth2.0/me", [ "query" => [ "access_token" => $token, ], ]); $openId = json_decode($this->jsonpToJson($response->getBody()->getContents()), true)["openid"]; $this->setOpenId($openId); $response = $this->getHttpClient()->get("https://graph.qq.com/user/get_user_info", [ "query" => [ "oauth_consumer_key" => $this->clientId, "access_token" => $token, "openid" => $openId, "format" => "json" ] ]); return json_decode($response->getBody(), true); }
最后就是注冊了,在 使用 Laravel Socialite 集成微信登錄 中我們已經談到過 Socialite 自定義驅動的實現機制:
app->make("LaravelSocialiteContractsFactory")->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() { } }
Laravel Socialite 對 OAuth 協議的流程進行了高度的抽象,并將相應的功能解耦,所以在自定義擴展時你并不需要做出太多,如果你想要了解的更多,你可以參考 larastarscn/socialite 的源碼,它只是簡單的為微信,QQ,微博的登錄提供了擴展驅動。
PS: 歡迎關注簡書 Laravel 專題,也歡迎 Laravel 相關文章的投稿 :),作者知識技能水平有限,如果你有更好的設計方案歡迎討論交流,如果有錯誤的地方也請批評指正,在此表示感謝謝謝 :)
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/30483.html
摘要:允許用戶提供一個令牌,而不是用戶名和密碼來訪問他們存放在特定服務提供者的數據。這樣,讓用戶可以授權第三方網站訪問他們存儲在另外服務提供者的某些特定信息,而非所有內容。 Laravel Socialite Laravel Socialite provides an expressive, fluent interface to OAuth authentication with Face...
摘要:目前支持的認證有。英文不好的同學比如我,下面是中文文檔通過擴展的,實現了很多第三方認證。國內的有微博微信豆瓣。至于和的具體值,這個是由新浪微博分發給你的,在新浪微博的授權回調頁中填寫。 前言 第三方登錄認證能簡化用戶登錄/注冊的操作,降低用戶登錄/注冊的門檻,對提高應用的用戶轉化率很有幫助。 Socialite Laravel 為我們提供了簡單、易用的方式,使用 Laravel Soc...
摘要:在詳解中使用解決了第三方賬號登錄集成的問題,那么在獲取到用戶資料之后呢集成多個社交賬號,該如何綁定同一個賬號本篇就讓我們來探討一下集成登錄的那點事。 Dearmadman 在 Laravel Socialite 詳解 中使用 larastarscn/socialite 解決了第三方賬號登錄集成的問題,那么在獲取到用戶資料之后呢?集成多個社交賬號,該如何綁定同一個賬號?本篇就讓我們來探討...
摘要:本文整理上國內相對較常用及以上版本的擴展包代碼生成文檔對象云存儲文檔消息閃存文檔編輯器代碼提示文檔文檔文檔圖片處理文檔微信開發文檔語言包文檔驗證碼文檔社會化登陸文檔系統日志文檔前端構建工具文檔跨域資源共享文檔基于的用戶認 本文整理Github上國內相對較常用Laravel5及以上版本的擴展包 laravel-generator(代碼生成) Github:https://github....
摘要:本文整理上國內相對較常用及以上版本的擴展包代碼生成文檔對象云存儲文檔消息閃存文檔編輯器代碼提示文檔文檔文檔圖片處理文檔微信開發文檔語言包文檔驗證碼文檔社會化登陸文檔系統日志文檔前端構建工具文檔跨域資源共享文檔基于的用戶認 本文整理Github上國內相對較常用Laravel5及以上版本的擴展包 laravel-generator(代碼生成) Github:https://github....
閱讀 2314·2021-11-08 13:13
閱讀 1245·2021-10-09 09:41
閱讀 1683·2021-09-02 15:40
閱讀 3186·2021-08-17 10:13
閱讀 2546·2019-08-29 16:33
閱讀 3122·2019-08-29 13:17
閱讀 3131·2019-08-29 11:00
閱讀 3295·2019-08-26 13:40