Laravel Socialite 是一個第一方 Laravel 包,可幫助開發人員在其應用程式中實現 OAuth 和 OAuth2 社交身份驗證。它內建了對 Facebook、Twitter、Google、LinkedIn、GitHub、GitLab 和 Bitbucket 的支援。社交名流可以透過社群包支援其他提供者。
這篇文章將:
TLDR:您可以在我的 GitHub 上查看已完成的專案。如果您只想閱讀完整的程式碼,請看一下它。
Socialite 是一個小包,其主要 API 主要由兩個主要方法組成:
還有針對設定範圍和可選參數的附加支援方法。您可以在社交名流文件中閱讀有關它們的資訊。
社交名流不會執行以下操作:它將這些功能的實作留給開發人員:
我們將建立一個小型社交項目,允許使用者透過 Google 進行身份驗證。為此,您必須建立 Google 應用程式。
先建立一個新的 Google Cloud 項目,然後為該項目配置 OAuth 同意畫面。將使用者類型設定為外部,然後啟用以下範圍:
設定同意畫面後,透過造訪 Google Cloud 憑證頁面建立 OAuth 2.0 用戶端 ID。保留客戶端ID和客戶端密鑰:我們稍後將在專案中使用它們。
建立一個新的 Laravel 專案:
laravel new socialite-tests
從安裝程式中選擇以下選項:
┌ Would you like to install a starter kit? ────────────────────┐ │ No starter kit │ └──────────────────────────────────────────────────────────────┘ ┌ Which testing framework do you prefer? ──────────────────────┐ │ Pest │ └──────────────────────────────────────────────────────────────┘ ┌ Which database will your application use? ───────────────────┐ │ SQLite │ └──────────────────────────────────────────────────────────────┘ ┌ Would you like to run the default database migrations? ──────┐ │ Yes │ └──────────────────────────────────────────────────────────────┘
切換到專案目錄並安裝Socialite。
laravel new socialite-tests
建立新的遷移。
┌ Would you like to install a starter kit? ────────────────────┐ │ No starter kit │ └──────────────────────────────────────────────────────────────┘ ┌ Which testing framework do you prefer? ──────────────────────┐ │ Pest │ └──────────────────────────────────────────────────────────────┘ ┌ Which database will your application use? ───────────────────┐ │ SQLite │ └──────────────────────────────────────────────────────────────┘ ┌ Would you like to run the default database migrations? ──────┐ │ Yes │ └──────────────────────────────────────────────────────────────┘
將以下程式碼放入database/migrations中新建立的遷移檔案中:
cd socialite-tests composer require laravel/socialite
此遷移新增了當使用者成功進行身份驗證時由社交名流提供的欄位。在我們的實作中,為了簡單起見,我們將這些欄位直接新增到使用者表中。如果您想支援比 Google 更多的供應商,您可能需要建立一個單獨的表格來儲存每個使用者的多個提供者。
我們將密碼設為可為空,因為如果使用者僅透過 Google 進行身份驗證,則永遠不會設定密碼。如果您的應用程式允許社交身份驗證和密碼身份驗證,則當使用者嘗試透過密碼登入時,您必須驗證密碼不為空或為空。
運行遷移。
php artisan make:migration add_socialite_fields_to_users
在 config/services.php 中,將以下程式碼區塊新增至 services 陣列的末端。您可以在設定文件中找到有效社交名流服務名稱的完整清單。
<?php // database/migrations/2024_12_31_075619_add_socialite_fields_to_users.php use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; return new class extends Migration { /** * Run the migrations. */ public function up(): void { Schema::table('users', function (Blueprint $table) { $table->string('google_id')->default(''); $table->string('google_token')->default(''); $table->string('google_refresh_token')->default(''); // If your app allows both password and social logins, you // MUST validate that the password is not blank during login. // If you do not, an attacker could gain access to an account // that uses social login by only knowing the email. $table->string('password')->nullable()->change(); }); } /** * Reverse the migrations. */ public function down(): void { Schema::table('users', function (Blueprint $table) { $table->dropColumn('google_id'); $table->dropColumn('google_token'); $table->dropColumn('google_refresh_token'); $table->string('password')->nullable(false)->change(); }); } };
使用您在「先決條件」部分中建立的 Google 應用程式中的憑證,將以下內容新增至 .env。
php artisan migrate
將routes/web.php的內容替換為以下程式碼。
// config/services.php 'google' => [ 'client_id' => env('GOOGLE_CLIENT_ID'), 'client_secret' => env('GOOGLE_CLIENT_SECRET'), 'redirect' => '/auth/google/callback', ],
此文件中的新程式碼實作了以下路由:
最後,將 resources/views/welcome.php 的內容替換為以下標記。
# .env GOOGLE_CLIENT_ID="your-google-client-id" GOOGLE_CLIENT_SECRET="your-google-client-secret"
完成後,我們可以透過執行開發伺服器來手動測試應用程式。
<?php // routes/web.php use App\Models\User; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Route; use Laravel\Socialite\Facades\Socialite; use Laravel\Socialite\Two\InvalidStateException; use Laravel\Socialite\Two\User as OAuth2User; Route::get('/', function () { return view('welcome'); }); Route::get('/auth/google/redirect', function () { return Socialite::driver('google')->redirect(); }); Route::get('/auth/google/callback', function () { try { /** @var OAuth2User $google_user */ $google_user = Socialite::driver('google')->user(); } catch (InvalidStateException $exception) { abort(400, $exception->getMessage()); } $user = User::updateOrCreate([ 'email' => $google_user->email, ], [ 'google_id' => $google_user->id, 'name' => $google_user->name, 'google_token' => $google_user->token, 'google_refresh_token' => $google_user->refreshToken, ]); Auth::login($user); return redirect('/'); }); Route::get('/auth/logout', function () { Auth::logout(); return redirect('/'); });
當您點擊使用 Google 登入連結時,您應該完成 OAuth2 流程並被重定向到主頁,您可以在其中查看有關來自 Google 的新建立使用者的信息。
我們的手動測試有效,但我們希望透過自動化測試來驗證我們將來不會意外破壞此功能。
我們可以使用以下命令建立一個新的測試檔案。
<!-- resources/views/welcome.php --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Laravel Socialite Testing Example</title> </head> <body> <h1>Laravel Socialite Testing Example</h1> @if (auth()->check()) <p>User is authenticated.</p> <p>Name: {{ auth()->user()->name }}</p> <p>Email: {{ auth()->user()->email }}</p> <p><a href="/auth/logout">Logout</a></p> @else <p>User is not authenticated.</p> <p> <a href="/auth/google/redirect">Login with Google</a> </p> @endif </body> </html>
將新建立的tests/Feature/AuthRoutesTest.php 的內容替換為以下內容。
php artisan serve
在測試重定向路由時,我們測試Socialite是否重定向到正確的URL並傳遞正確的URL參數。
在測試回呼路由時,我們模擬了 Socialite。模擬不是我最喜歡的選擇:在理想的世界中,我們可以將 Socialite 替換為另一個 OAuth2 實現,並且我們的測試仍然有效。但是,沒有直接的方法來連接社交名流發送的授權授予請求以裝飾存取權杖。正因為如此,模擬是測試社交名流的最實用的方法。
透過 Mockery 模擬流暢的 API 非常乏味:您必須從最終呼叫開始並向後進行。
這是我們的回呼端點呼叫的 Socialite 方法。
laravel new socialite-tests
以下是如何透過 Mockery 來嘲笑它:
┌ Would you like to install a starter kit? ────────────────────┐ │ No starter kit │ └──────────────────────────────────────────────────────────────┘ ┌ Which testing framework do you prefer? ──────────────────────┐ │ Pest │ └──────────────────────────────────────────────────────────────┘ ┌ Which database will your application use? ───────────────────┐ │ SQLite │ └──────────────────────────────────────────────────────────────┘ ┌ Would you like to run the default database migrations? ──────┐ │ Yes │ └──────────────────────────────────────────────────────────────┘
最後,我們進行了測試,以確保直接導航到 OAuth 流程之外的回調 URL 會傳回 400 狀態碼。我們將對 Socialite::driver('google')->user() 的呼叫包裝在 try/catch 區塊內的回呼端點中。如果我們沒有將 Socialite 呼叫包裝在 try/catch 區塊中,並且有人在瀏覽器中輸入了回調 URL,則端點將引發帶有 HTTP 500 狀態碼的異常。如果您的團隊設定了 500 個狀態代碼的監控,則可能會導致某人在半夜收到尋呼。
這是一個最小的集成,還有很多可以實現的功能。如果我們要實現與社交提供者的集成,其中使用者的電子郵件可能會更改,則此實作將不起作用,因為它與電子郵件地址相符。如果用戶可以在我們的應用程式中更改他們的電子郵件地址,那麼由於同樣的原因,此實作也將無法運作。但是,現在您已經了解如何測試 Socialite,您可以為這些場景編寫測試並修改底層實現,以便它們通過。
在我了解如何建立自己的實作、如何測試它以及我應該考慮什麼之前,我閱讀了很多有關 Socialite 的部落格文章和論壇貼文。我想對其中的一些人表示感謝。
如果您有興趣深入挖掘,請閱讀這些內容。另外,如果您對本文的第 2 部分感興趣,請告訴我,我將深入探討處理多個社交提供者、處理使用者更改電子郵件地址或處理刷新權杖。
以上是在 Laravel 中實作和測試社交名流身份驗證的詳細內容。更多資訊請關注PHP中文網其他相關文章!