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