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