??Socialite社會化認(rèn)證(第三方登入)支持QQ/微信/微博/抖音/支付寶/淘寶等20幾種

webman-socialite
webman-socialite 是一個 OAuth2 社會化認(rèn)證工具。 它借鑒于 laravel/socialite ,你可以輕易的運行在webman的laravel/tp/yii等項目中使用它
該工具現(xiàn)已支持平臺有:Facebook,Github,Google,Linkedin,Outlook,QQ,TAPD,支付寶,淘寶,百度,釘釘,微博,微信,抖音,飛書,Lark,豆瓣,企業(yè)微信,騰訊云,Line,Gitee,Coding。
如果你覺得方便了你,可以為我點個小星星點擊這里 :heart:
安裝
composer require shopwwi/webman-socialite
配置
在使用 Socialite
之前,您還需要為應(yīng)用程序使用的 OAuth
服務(wù)添加憑據(jù)。 這些憑證應(yīng)該放在你的 config/plugin/shopwwi/socialite/app.php
配置文件中,并且應(yīng)該使用密鑰 facebook,twitter,linkedin,google,github,gitlab 或 bitbucket, 取決于您的應(yīng)用程序所需的提供商。 例如:
'driver' => [
...
'qq' => [
'provider' => \Shopwwi\WebmanSocialite\Providers\QqProvider::class,
'client_id' => '',
'client_secret' => '',
'redirect' => 'http://your-callback-url',
],
...
]
使用方法
接下來,就要對用戶認(rèn)證了!這需要兩個路由:一個路由用于把用戶重定向到 OAuth provider,另一個則用于在認(rèn)證完成后接收相應(yīng) provider
的回調(diào)請求??梢酝ㄟ^ Socialite facade
的方式來訪問 Socialite:
<?php
namespace app\controller\auth;
use support\Request;
use Shopwwi\WebmanSocialite\Facade\Socialite;
class QqController
{
/**
* 將用戶重定向到 QQ 的授權(quán)頁面
*
* @return
*/
public function redirect(Request $request)
{
$redirect = Socialite::driver('qq')->redirect();
return redirect($redirect);
}
/**
* 從 QQ 獲取用戶信息
*
*/
public function callback(Request $request)
{
$code = $request->input('code');
$qqUser = Socialite::driver('qq')->userFromCode($code);
//示例
$user = User::where('qq_id', $qqUser->id)->first();
if ($user) {
$user->update([
'qq_token' => $qqUser->access_token,
'qq_refresh_token' => $qqUser->refresh_token,
]);
} else {
$user = User::create([
'name' => $qqUser->name,
'email' => $qqUser->email,
'qq_id' => $qqUser->id,
'qq_token' => $qqUser->access_token,
'qq_refresh_token' => $qqUser->refresh_token,
]);
}
Auth::login($user);
return redirect('/index');
}
}
配置
擴展自定義服務(wù)提供程序
你可以很輕松的對socialite進(jìn)行擴展來滿足你不同的第三方登入需求
1.直接在config配置里添加你的應(yīng)用驅(qū)動
'driver' => [
..
'line' => [
'provider' => \app\provider\LineProvider::class,
'client_id' => 'your-app-id',
'client_secret' => 'your-app-secret',
'redirect' => 'http://your-callback-url',
],
..
];
$socialite = Socialite::driver('line')->redirect();
2.使用閉包函數(shù)進(jìn)行擴展
$config = [
'line' =>[
'provider' => 'line',
'client_id' => 'your-app-id',
'client_secret' => 'your-app-secret',
'redirect' => 'http://your-callback-url',
]
];
$socialite = Socialite::config(new \Shopwwi\WebmanSocialite\Config($config))->extend('line', function(array $config) {
return new LineProvider($config);
})->driver('line')->redirect();
// 下面直接注入也是可以的哈
$config = [
'line' =>[
'provider' => \app\provider\LineProvider::class,
'client_id' => 'your-app-id',
'client_secret' => 'your-app-secret',
'redirect' => 'http://your-callback-url',
]
];
$socialite = Socialite::config(new \Shopwwi\WebmanSocialite\Config($config))->driver('line')->redirect();
3.接下來為 AppleProvider
設(shè)置實際操作方法:
你的自定義服務(wù)提供類必須實現(xiàn)\Shopwwi\WebmanSocialite\Contracts\Provider
接口
namespace app\provider;
class LineProvider implements \Shopwwi\WebmanSocialite\Contracts\Provider
{
//...
}
下面的示例繼承了 \Shopwwi\WebmanSocialite\Providers\AbstractProvider
大多數(shù)邏輯都是實現(xiàn)好了的 微調(diào)即可
namespace app\provider;
use Shopwwi\WebmanSocialite\Providers\AbstractProvider;
use Shopwwi\WebmanSocialite\Contracts;
use Shopwwi\WebmanSocialite\AbstractUser;
class LineProvider extends AbstractProvider
{
public const NAME = 'line';
protected string $baseUrl = 'https://api.line.me/oauth2/';
protected string $version = 'v2.1';
protected array $scopes = ['profile'];
protected function getAuthUrl(): string
{
$this->state = $this->state ?: \md5(\uniqid(Contracts\SHOPWWI_SOC_STATE, true));
return $this->buildAuthUrlFromBase('https://access.line.me/oauth2/'.$this->version.'/authorize');
}
protected function getTokenUrl(): string
{
return $this->baseUrl.$this->version.'/token';
}
/**
* @param string $code
* @return array
*/
protected function getTokenFields(string $code): array
{
return parent::getTokenFields($code) + [Contracts\SHOPWWI_SOC_GRANT_TYPE => Contracts\SHOPWWI_SOC_AUTHORIZATION_CODE];
}
/**
* @param string $token
* @return array
* @throws \GuzzleHttp\Exception\GuzzleException
*/
protected function getUserByToken(string $token): array
{
$response = $this->getHttpClient()->get(
'https://api.line.me/v2/profile',
[
'headers' => [
'Accept' => 'application/json',
'Authorization' => 'Bearer '.$token,
],
]
);
return $this->fromJsonBody($response);
}
/**
* @param array $user
* @return Contracts\User
*/
protected function mapUserToObject(array $user): Contracts\User
{
return new AbstractUser([
Contracts\SHOPWWI_SOC_ID => $user['userId'] ?? null,
Contracts\SHOPWWI_SOC_NAME => $user['displayName'] ?? null,
Contracts\SHOPWWI_SOC_NICKNAME => $user['displayName'] ?? null,
Contracts\SHOPWWI_SOC_AVATAR => $user['pictureUrl'] ?? null,
Contracts\SHOPWWI_SOC_EMAIL => null,
]);
}
}
平臺
不同的平臺有不同的配置方法,為了確保工具的正常運行,所以請確保你所使用的平臺的配置都是如期設(shè)置的。
支付寶
請按如下方式配置
$code = \request()->input('code');
$user = Socialite::driver('alipay')->userFromCode($code);
// 詳見文檔后面 "User interface"
$user->getId();
$user->getNickname();
$user->getUsername();
$user->getName();
...
釘釘
如文檔所示
注意:該工具僅支持 QR code 連接到第三方網(wǎng)站,用來獲取用戶信息(openid, unionid 和 nickname)
$code = \request()->input('code');
$user = Socialite::driver('dingtalk')->userFromCode($code);
// 詳見文檔后面 "User interface"
$user->getId();
$user->getNickname();
$user->getUsername();
$user->getName();
...
抖音
$code = \request()->input('code');
$user = Socialite::driver('douyin')->userFromCode($code);
// 通過access_token獲取用戶信息時,需先設(shè)置openId
$openId = '4154d454..5561';
$token = '';
$user = Socialite::driver('douyin')->withOpenId($openId)->userFromToken($token);
頭條
$code = \request()->input('code');
$user = Socialite::driver('toutiao')->userFromCode($code);
// 通過access_token獲取用戶信息時,需先設(shè)置openId
$openId = '4154d454..5561';
$token = '';
$user = Socialite::driver('toutiao')->withOpenId($openId)->userFromToken($token);
西瓜
$code = \request()->input('code');
$user = Socialite::driver('toutiao')->userFromCode($code);
//通過access_token獲取用戶信息時,需先設(shè)置openId
$openId = '4154d454..5561';
$token = '';
$user = Socialite::driver('toutiao')->withOpenId($openId)->userFromToken($token);
百度
其他配置沒啥區(qū)別,在用法上,可以很輕易的選擇重定向登錄頁面的模式,通過 withDisplay()
- page:全屏形式的授權(quán)頁面 (默認(rèn)),適用于 web 應(yīng)用。
- popup: 彈框形式的授權(quán)頁面,適用于桌面軟件應(yīng)用和 web 應(yīng)用。
- dialog: 浮層形式的授權(quán)頁面,只能用于站內(nèi) web 應(yīng)用。
- mobile: Iphone/Android 等智能移動終端上用的授權(quán)頁面,適用于 Iphone/Android 等智能移動終端上的應(yīng)用。
- tv: 電視等超大顯示屏使用的授權(quán)頁面。
- pad: IPad/Android 等智能平板電腦使用的授權(quán)頁面。
$authUrl = Socialite::driver('baidu')->withDisplay('mobile')->redirect();
popup
模式是工具內(nèi)默認(rèn)的使用模式。basic
是默認(rèn)使用的 scopes 值。
飛書
通過一些簡單的方法配置 app_ticket 就能使用內(nèi)部應(yīng)用模式
$code = \request()->input('code');
$user = Socialite::driver('feishu')->withInternalAppMode()->userFromCode($code);
$appTicket = '';
$code = \request()->input('code');
$user = Socialite::driver('feishu')->withDefaultMode()->withAppTicket($appTicket)->userFromCode($code);
Lark
通過一些簡單的方法配置 app_ticket 就能使用內(nèi)部應(yīng)用模式
$code = \request()->input('code');
$user = Socialite::driver('lark')->withInternalAppMode()->userFromCode($code);
$appTicket = '';
$code = \request()->input('code');
$user = Socialite::driver('lark')->withDefaultMode()->withAppTicket($appTicket)->userFromCode($code);
淘寶
其他配置與其他平臺的一樣,你能選擇你想要展示的重定向頁面類型通過使用 withView()
$authUrl = Socialite::driver('taobao')->withView('wap')->redirect();
web
模式是工具默認(rèn)使用的展示方式, user_info
是默認(rèn)使用的 scopes 范圍值。
微信
我們支持開放平臺代表公眾號進(jìn)行第三方平臺網(wǎng)頁授權(quán)。
你只需要像下面這樣輸入你的配置。官方賬號不需要授權(quán)。
'wechat' => [
'provider' => \Shopwwi\WebmanSocialite\Providers\WeChatProvider::class,
'client_id' => 'your-app-id',
'client_secret' => 'your-app-secret',
'redirect' => 'http://your-callback-url',
// 開放平臺 - 第三方平臺所需
'component' => [
// or 'app_id', 'component_app_id' as key
'id' => 'component-app-id',
// or 'app_token', 'access_token', 'component_access_token' as key
'token' => 'component-access-token',
]
],
Coding
您需要額外配置 team_url
為您的團隊域名
其他一些技巧
訪問作用域
在重定向用戶之前,你還可以使用 scopes
方法在請求中添加其他「作用域」。此方法將覆蓋所有現(xiàn)有的作用域:
$redirect = Socialite::driver('qq')->scopes(['scope1', 'scope2'])->redirect();
回調(diào)鏈接
你也可以動態(tài)設(shè)置 redirect_uri
,你可以使用以下方法來改變 redirect_uri
URL:
$url = 'your callback url.';
Socialite::driver('qq')->redirect($url);
// or
Socialite::driver('qq')->withRedirectUrl($url)->redirect();
State
你的應(yīng)用程序可以使用一個狀態(tài)參數(shù)來確保響應(yīng)屬于同一個用戶發(fā)起的請求,從而防止跨站請求偽造 (CSFR) 攻擊。當(dāng)惡意攻擊者欺騙用戶執(zhí)行不需要的操作 (只有用戶有權(quán)在受信任的 web 應(yīng)用程序上執(zhí)行) 時,就會發(fā)生 CSFR 攻擊,所有操作都將在不涉及或警告用戶的情況下完成。
這里有一個最簡單的例子,說明了如何提供狀態(tài)可以讓你的應(yīng)用程序更安全。在本例中,我們使用會話 ID 作為狀態(tài)參數(shù),但是您可以使用您想要為狀態(tài)創(chuàng)建值的任何邏輯。
帶著 state
參數(shù)的重定向
<?php
session_start();
// Assign to state the hashing of the session ID
$state = hash('sha256', session_id());
$url = Socialite::driver('qq')->withState($state)->redirect();
return redirect($url);
檢驗回調(diào)的 state
一旦用戶授權(quán)你的應(yīng)用程序,用戶將被重定向回你的應(yīng)用程序的 redirect_uri。OAuth 服務(wù)器將不加修改地返回狀態(tài)參數(shù)。檢查 redirect_uri 中提供的狀態(tài)是否與應(yīng)用程序生成的狀態(tài)相匹配:
<?php
session_start();
$state = \request()->input('state');
$code = \request()->input('code');
// Check the state received with current session id
if ($state != hash('sha256', session_id())) {
exit('State does not match!');
}
$user = Socialite::driver('qq')->userFromCode($code);
// authorized
可選參數(shù)
許多 OAuth providers 支持重定向請求中的可選參數(shù)。 要在請求中包含任何可選參數(shù),請使用關(guān)聯(lián)數(shù)組調(diào)用 with
方法:
$response = Socialite::driver('qq')->with(['hd' => 'example.com'])->redirect();
返回用戶信息
標(biāo)準(zhǔn)的 user api:
$user = Socialite::driver('qq')->userFromCode($code);
你可以像這樣以數(shù)組鍵的形式獲取 user 屬性:
$user['id'];
$user['nickname'];
$user['name'];
$user['email'];
...
或者使用該 User
對象的方法:
$user->getId();
$user->getNickname();
$user->getName();
$user->getEmail();
$user->getAvatar();
$user->getRaw();
$user->getAccessToken();
$user->getRefreshToken();
$user->getExpiresIn();
$user->getTokenResponse();
從 OAuth API 響應(yīng)中取得原始數(shù)據(jù)
$user->getRaw()
方法會返回一個 array。
當(dāng)你使用 userFromCode() 想要獲取 token 響應(yīng)的原始數(shù)據(jù)
$user->getTokenResponse()
方法會返回一個 array 里面是響應(yīng)從獲取 token 時候 API 返回的響應(yīng)。
注意:當(dāng)你使用
userFromCode()
時,這個方法只返回一個 有效的數(shù)組,否則將返回 null,因為userFromToken()
沒有 token 的 HTTP 響應(yīng)。
通過 access token 獲取用戶信息
$accessToken = 'xxxxxxxxxxx';
$user = $socialite->userFromToken($accessToken);
參照
- Alipay - 用戶信息授權(quán)
- DingTalk - 掃碼登錄第三方網(wǎng)站
- Google - OpenID Connect
- Github - Authorizing OAuth Apps
- Facebook - Graph API
- Linkedin - Authenticating with OAuth 2.0
- 微博 - OAuth 2.0 授權(quán)機制說明
- QQ - OAuth 2.0 登錄 QQ
- 騰訊云 - OAuth2.0
- 微信公眾平臺 - OAuth 文檔
- 微信開放平臺 - 網(wǎng)站應(yīng)用微信登錄開發(fā)指南
- 微信開放平臺 - 代公眾號發(fā)起網(wǎng)頁授權(quán)
- 企業(yè)微信 - OAuth 文檔
- 企業(yè)微信第三方應(yīng)用 - OAuth 文檔
- 豆瓣 - OAuth 2.0 授權(quán)機制說明
- 抖音 - 網(wǎng)站應(yīng)用開發(fā)指南
- 飛書 - 授權(quán)說明
- Lark - 授權(quán)說明
- Tapd - 用戶授權(quán)說明
- Line - OAuth 2.0
- Gitee - OAuth文檔
License
MIT