Socialite 是一個OAuth2 認證工具。 它的靈感來自laravel/socialite , 你可以很輕易的在任何PHP 專案中使用它。英文文檔
該工具現已支援平台有:Facebook,Github,Google,Linkedin,Outlook,QQ,TAPD,支付寶,淘寶,百度,釘釘,微博,微信,抖音,飛書,Lark,豆瓣,企業微信,騰訊雲,Line,Gitee,Coding。
如果你喜歡我的專案並想支持我,請點擊這裡❤️
PHP >= 8.0.2
composer require " overtrue/socialite " -vvv
使用者只需要建立對應配置變量,然後透過工具為各個平台建立認證應用,並輕鬆取得該平台的access_token 和使用者相關資訊。工具實作邏輯詳見參考各大平台OAuth2 文件。
工具使用大致分為以下幾個步驟:
為Laravel 用戶創建的更方便的整合的套件: overtrue/laravel-socialite
authorize.php
: 讓使用者跳轉至平台認證
<?php
use Overtrue Socialite SocialiteManager ;
$ config = [
' github ' => [
' client_id ' => ' your-app-id ' ,
' client_secret ' => ' your-app-secret ' ,
' redirect ' => ' http://localhost/socialite/callback.php ' ,
],
];
$ socialite = new SocialiteManager ( $ config );
$ url = $ socialite -> create ( ' github ' )-> redirect ();
return redirect ( $ url );
callback.php
:
<?php
use Overtrue Socialite SocialiteManager ;
$ config = [
' github ' => [
' client_id ' => ' your-app-id ' ,
' client_secret ' => ' your-app-secret ' ,
' redirect ' => ' http://localhost/socialite/callback.php ' ,
],
];
$ socialite = new SocialiteManager ( $ config );
$ code = request ()-> query ( ' code ' );
$ user = $ socialite -> create ( ' github ' )-> userFromCode ( $ code );
$ user -> getId (); // 1472352
$ user -> getNickname (); // "overtrue"
$ user -> getUsername (); // "overtrue"
$ user -> getName (); // "安正超"
$ user -> getEmail (); // "[email protected]"
. . .
為每個平台設定相同的鍵值對後就能開箱即用: client_id
, client_secret
, redirect
.
範例:
$ config = [
' weibo ' => [
' client_id ' => ' your-app-id ' ,
' client_secret ' => ' your-app-secret ' ,
' redirect ' => ' http://localhost/socialite/callback.php ' ,
],
' facebook ' => [
' client_id ' => ' your-app-id ' ,
' client_secret ' => ' your-app-secret ' ,
' redirect ' => ' http://localhost/socialite/callback.php ' ,
],
];
你可以使用任意你喜歡的名字對每個平台進行命名,比如說foo
, 採用別名的方法後需要在配置中多設定一個provider
鍵,這樣才能告訴工具包如何正確找到你想要的程式:
$ config = [
// 为 github 应用起别名为 foo
' foo ' => [
' provider ' => ' github ' , // <-- provider name
' client_id ' => ' your-app-id ' ,
' client_secret ' => ' your-app-secret ' ,
' redirect ' => ' http://localhost/socialite/callback.php ' ,
],
// 另外一个名字叫做 bar 的 github 应用
' bar ' => [
' provider ' => ' github ' , // <-- provider name
' client_id ' => ' your-app-id ' ,
' client_secret ' => ' your-app-secret ' ,
' redirect ' => ' http://localhost/socialite/callback.php ' ,
],
//...
];
$ socialite = new SocialiteManager ( $ config );
$ appFoo = $ socialite -> create ( ' foo ' );
$ appBar = $ socialite -> create ( ' bar ' );
你可以很容易的從自訂的服務提供中建立應用,只需要遵循如下兩點:
使用自訂建立器
如下程式碼所示,為foo 應用程式定義了服務提供名,但是工具本身還未支持,所以使用建立器extend()
,以閉包函數的形式為該服務提供建立一個實例。
$ config = [
' foo ' => [
' provider ' => ' myprovider ' , // <-- 一个工具还未支持的服务提供程序
' client_id ' => ' your-app-id ' ,
' client_secret ' => ' your-app-secret ' ,
' redirect ' => ' http://localhost/socialite/callback.php ' ,
],
];
$ socialite = new SocialiteManager ( $ config );
$ socialite -> extend ( ' myprovider ' , function ( array $ config ) {
return new MyCustomProvider ( $ config );
});
$ app = $ socialite -> create ( ' foo ' );
Important
?你的自訂服務提供類別必須實作OvertrueSocialiteContractsProviderInterface
接口
class MyCustomProvider implements Overtrue Socialite Contracts ProviderInterface
{
//...
}
接下來為provider
設定該類別名稱讓工具可以找到該類別並實例化:
$ config = [
' foo ' => [
' provider ' => MyCustomProvider::class, // <-- 类名
' client_id ' => ' your-app-id ' ,
' client_secret ' => ' your-app-secret ' ,
' redirect ' => ' http://localhost/socialite/callback.php ' ,
],
];
$ socialite = new SocialiteManager ( $ config );
$ app = $ socialite -> create ( ' foo ' );
不同的平台有不同的配置方法,為了確保工具的正常運行,所以請確保你所使用的平台的配置都是如期設定的。
請如下配置
$ config = [
' alipay ' => [
// 这个键名还能像官方文档那样叫做 'app_id'
' client_id ' => ' your-app-id ' ,
// 请根据官方文档,在官方管理后台配置 RSA2
// 注意: 这是你自己的私钥
// 注意: 不允许私钥内容有其他字符
// 建议: 为了保证安全,你可以将文本信息从磁盘文件中读取,而不是在这里明文
' rsa_private_key ' => ' your-rsa-private-key ' ,
// 确保这里的值与你在服务后台绑定的地址值一致
// 这个键名还能像官方文档那样叫做 'redirect_url'
' redirect ' => ' http://localhost/socialite/callback.php ' ,
// 沙箱模式接入地址见 https://opendocs.alipay.com/open/220/105337#%E5%85%B3%E4%BA%8E%E6%B2%99%E7%AE%B1
' sandbox ' => false ,
]
. . .
];
$ socialite = new SocialiteManager ( $ config );
$ user = $ socialite -> create ( ' alipay ' )-> userFromCode ( ' here is auth code ' );
// 详见文档后面 "User interface"
$ user -> getId (); // 1472352
$ user -> getNickname (); // "overtrue"
$ user -> getUsername (); // "overtrue"
$ user -> getName (); // "安正超"
. . .
本工具暫時只支援RSA2 個人私鑰認證方式。
如文件所示
注意:此工具僅支援QR code 連接到第三方網站,用來取得使用者資訊(opeid, unionid 和nickname)
$ config = [
' dingtalk ' => [
// or 'app_id'
' client_id ' => ' your app id ' ,
// or 'app_secret'
' client_secret ' => ' your app secret ' ,
// or 'redirect_url'
' redirect ' => ' redirect URL '
]
];
$ socialite = new SocialiteManager ( $ config );
$ user = $ socialite -> create ( ' dingtalk ' )-> userFromCode ( ' here is auth code ' );
// 详见文档后面 "User interface"
$ user -> getId (); // 1472352
$ user -> getNickname (); // "overtrue"
$ user -> getUsername (); // "overtrue"
$ user -> getName (); // "安正超"
. . .
注意: 使用抖音服務提供的時候,如果你想直接使用access_token 取得使用者資訊時,請先設定openid。 先呼叫
withOpenId()
再呼叫userFromToken()
$ config = [
' douyin ' => [
' client_id ' => ' your app id ' ,
' client_secret ' => ' your app secret ' ,
' redirect ' => ' redirect URL '
]
];
$ socialite = new SocialiteManager ( $ config );
$ user = $ socialite -> create ( ' douyin ' )-> userFromCode ( ' here is auth code ' );
$ user = $ socialite -> create ( ' douyin ' )-> withOpenId ( ' openId ' )-> userFromToken ( ' here is the access token ' );
注意: 使用
头条
服務提供的時候,如果你想直接使用access_token 取得使用者資訊時,請先設定openid。 先呼叫withOpenId()
再呼叫userFromToken()
$ config = [
' toutiao ' => [
' client_id ' => ' your app id ' ,
' client_secret ' => ' your app secret ' ,
' redirect ' => ' redirect URL '
]
];
$ socialite = new SocialiteManager ( $ config );
$ user = $ socialite -> create ( ' toutiao ' )-> userFromCode ( ' here is auth code ' );
$ user = $ socialite -> create ( ' toutiao ' )-> withOpenId ( ' openId ' )-> userFromToken ( ' here is the access token ' );
注意: 使用
西瓜
服務提供的時候,如果你想直接使用access_token 取得使用者資訊時,請先設定openid。 先呼叫withOpenId()
再呼叫userFromToken()
$ config = [
' xigua ' => [
' client_id ' => ' your app id ' ,
' client_secret ' => ' your app secret ' ,
' redirect ' => ' redirect URL '
]
];
$ socialite = new SocialiteManager ( $ config );
$ user = $ socialite -> create ( ' xigua ' )-> userFromCode ( ' here is auth code ' );
$ user = $ socialite -> create ( ' xigua ' )-> withOpenId ( ' openId ' )-> userFromToken ( ' here is the access token ' );
其他配置沒啥區別,在用法上,可以很輕易的選擇重定向登入頁面的模式,透過withDisplay()
$ authUrl = $ socialite -> create ( ' baidu ' )-> withDisplay ( ' mobile ' )-> redirect ();
popup
模式是工具內預設的使用模式。 basic
是預設使用的scopes 值。
透過一些簡單的方法來設定app_ticket 就能使用內部應用模式
$ config = [
' feishu ' => [
// or 'app_id'
' client_id ' => ' your app id ' ,
// or 'app_secret'
' client_secret ' => ' your app secret ' ,
// or 'redirect_url'
' redirect ' => ' redirect URL ' ,
// 如果你想使用使用内部应用的方式获取 app_access_token
// 对这个键设置了 'internal' 值那么你已经开启了内部应用模式
' app_mode ' => ' internal '
]
];
$ socialite = new SocialiteManager ( $ config );
$ feishuDriver = $ socialite -> create ( ' feishu ' );
$ feishuDriver -> withInternalAppMode ()-> userFromCode ( ' here is code ' );
$ feishuDriver -> withDefaultMode ()-> withAppTicket ( ' app_ticket ' )-> userFromCode ( ' here is code ' );
透過一些簡單的方法來設定app_ticket 就能使用內部應用模式
$ config = [
' lark ' => [
// or 'app_id'
' client_id ' => ' your app id ' ,
// or 'app_secret'
' client_secret ' => ' your app secret ' ,
// or 'redirect_url'
' redirect ' => ' redirect URL ' ,
// 如果你想使用使用内部应用的方式获取 app_access_token
// 对这个键设置了 'internal' 值那么你已经开启了内部应用模式
' app_mode ' => ' internal '
]
];
$ socialite = new SocialiteManager ( $ config );
$ larkDriver = $ socialite -> create ( ' lark ' );
$ larkDriver -> withInternalAppMode ()-> userFromCode ( ' here is code ' );
$ larkDriver -> withDefaultMode ()-> withAppTicket ( ' app_ticket ' )-> userFromCode ( ' here is code ' );
其他配置與其他平台的一樣,你可以選擇你想要展示的重定向頁面類型透過使用withView()
$ authUrl = $ socialite -> create ( ' taobao ' )-> withView ( ' wap ' )-> redirect ();
web
模式是工具預設使用的展示方式, user_info
是預設使用的scopes 範圍值。
我們支持開放平台代表公眾號進行第三方平台網頁授權。
你只需要像下面這樣輸入你的配置。官方帳號不需要授權。
. . .
[
' wechat ' =>
[
' client_id ' => ' client_id ' ,
' client_secret ' => ' client_secret ' ,
' redirect ' => ' redirect-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 ' ,
]
]
],
...
您需要額外配置team_url
為您的團隊域名,例如:
$ config = [
' coding ' => [
' team_url ' => ' https://{your-team}.coding.net ' ,
' client_id ' => ' your app id ' ,
' client_secret ' => ' your app secret ' ,
' redirect ' => ' redirect URL ' ,
]
];
您可能需要設定responseType,可以使用withResponseType
函數進行設置,預設是code
也可以設定為id_token
或code
& id_token
https://developer.paypal.com/docs/log-in-with-paypal/integrate/generate-button/
$ config = [
' paypal ' => [
' client_id ' => ' AT****************** ' ,
' client_secret ' => ' EK************** ' ,
' sandbox ' => false ,
' redirect_url ' => " nativexo://paypalpay " ,
],
];
在重新導向使用者之前,您也可以使用scopes()
方法在請求上設定「範圍」。此方法將覆寫所有現有的作用域:
$ response = $ socialite -> create ( ' github ' )
-> scopes ([ ' scope1 ' , ' scope2 ' ])-> redirect ();
你也可以動態設定' redirect_uri ',你可以使用以下方法來改變redirect_uri
URL:
$ url = ' your callback url. ' ;
$ socialite -> redirect ( $ url );
// or
$ socialite -> withRedirectUrl ( $ url )-> redirect ();
你的應用程式可以使用一個狀態參數來確保回應屬於同一個使用者發起的請求,從而防止跨站請求偽造(CSFR) 攻擊。當惡意攻擊者欺騙使用者執行不需要的操作(只有使用者有權在受信任的web 應用程式上執行) 時,就會發生CSFR 攻擊,所有操作都將在不涉及或警告使用者的情況下完成。
這裡有一個最簡單的例子,說明如何提供狀態可以讓你的應用程式更安全。在本例中,我們使用會話ID 作為狀態參數,但是您可以使用您想要為狀態建立值的任何邏輯。
state
參數的重定向 <?php
session_start ();
$ config = [
//...
];
// Assign to state the hashing of the session ID
$ state = hash ( ' sha256 ' , session_id ());
$ socialite = new SocialiteManager ( $ config );
$ url = $ socialite -> create ( ' github ' )-> withState ( $ state )-> redirect ();
return redirect ( $ url );
state
一旦用戶授權你的應用程序,用戶將被重定向回你的應用程式的redirect_uri。 OAuth 伺服器將不加修改地傳回狀態參數。檢查redirect_uri 中提供的狀態是否與應用程式產生的狀態相符:
<?php
session_start ();
$ state = request ()-> query ( ' state ' );
$ code = request ()-> query ( ' code ' );
// Check the state received with current session id
if ( $ state != hash ( ' sha256 ' , session_id ())) {
exit ( ' State does not match! ' );
}
$ user = $ socialite -> create ( ' github ' )-> userFromCode ( $ code );
// authorized
查看更多關於state
參數的文檔
要在請求中包含任何可選參數,呼叫with()
方法傳入一個你想要設定的關聯數組:
$ response = $ socialite -> create ( ' google ' )
-> with ([ ' hd ' => ' example.com ' ])-> redirect ();
$ user = $ socialite -> create ( ' github ' )-> userFromCode ( $ code );
{
"id" : 1472352 ,
"nickname" : " overtrue " ,
"name" : "安正超" ,
"email" : " [email protected] " ,
"avatar" : " https://avatars.githubusercontent.com/u/1472352?v=3 " ,
"raw" : {
"login" : " overtrue " ,
"id" : 1472352 ,
"avatar_url" : " https://avatars.githubusercontent.com/u/1472352?v=3 " ,
"gravatar_id" : " " ,
"url" : " https://api.github.com/users/overtrue " ,
"html_url" : " https://github.com/overtrue " ,
...
},
"token_response" : {
"access_token" : " 5b1dc56d64fffbd052359f032716cc4e0a1cb9a0 " ,
"token_type" : " bearer " ,
"scope" : " user:email "
}
}
你可以像這樣以數組鍵的形式取得user 屬性:
$ user [ ' id ' ]; // 1472352
$ user [ ' nickname ' ]; // "overtrue"
$ user [ ' name ' ]; // "安正超"
$ user [ ' email ' ]; // "[email protected]"
. . .
或使用該User
物件的方法:
mixed $ user -> getId ();
?string $ user -> getNickname ();
?string $ user -> getName ();
?string $ user -> getEmail ();
?string $ user -> getAvatar ();
?string $ user -> getRaw ();
?string $ user -> getAccessToken ();
?string $ user -> getRefreshToken ();
?int $ user -> getExpiresIn ();
?array $ user -> getTokenResponse ();
$user->getRaw()
方法會回傳一個array 。
$user->getTokenResponse()
方法會回傳一個array裡面是回應從取得token 時候API 回傳的回應。
注意:當你使用
userFromCode()
時,這個方法只會傳回一個有效的數組,否則會傳回null ,因為userFromToken()
沒有token 的HTTP 回應。
$ accessToken = ' xxxxxxxxxxx ' ;
$ user = $ socialite -> userFromToken ( $ accessToken );
想知道如何從零開始建立PHP 擴充包?
請關注我的實戰課程,我會在此課程中分享一些擴展開發經驗—— 《PHP 擴展包實戰教程- 從入門到發布》
MIT