首頁 > 後端開發 > php教程 > 在 Laravel 中實作和測試社交名流身份驗證

在 Laravel 中實作和測試社交名流身份驗證

DDD
發布: 2025-01-03 11:17:42
原創
150 人瀏覽過

Implementing & testing Socialite authentication in Laravel

Laravel Socialite 是一個第一方 Laravel 包,可幫助開發人員在其應用程式中實現 OAuth 和 OAuth2 社交身份驗證。它內建了對 Facebook、Twitter、Google、LinkedIn、GitHub、GitLab 和 Bitbucket 的支援。社交名流可以透過社群包支援其他提供者。

這篇文章將:

  • 解釋社交名流做什麼、不做什麼。
  • 展示如何透過 Socialite 將 Google 驗證整合到新的 Laravel 專案中。
  • 展示測試社交名流的範例。

TLDR:您可以在我的 GitHub 上查看已完成的專案。如果您只想閱讀完整的程式碼,請看一下它。

Laravel Socialite 做什麼、不做什麼?

Socialite 是一個小包,其主要 API 主要由兩個主要方法組成:

  • Socialite::driver($authProvider)->redirect() 將把使用者重新導向到指定的驗證提供者,透過 URL 參數將任何必要的資訊傳遞給提供者。
  • Socialite::driver($authProvider)->user() 擷取從驗證提供者傳回的使用者資料並提供給端點。

還有針對設定範圍和可選參數的附加支援方法。您可以在社交名流文件中閱讀有關它們的資訊。

社交名流不會執行以下操作:它將這些功能的實作留給開發人員:

  • ❌ 建立儲存社交驗證資料所需的資料庫表或欄位。
  • ❌ 建立身份驗證過程中不存在的使用者。
  • ❌ 在 OAuth 流程成功後對使用者進行身份驗證。
  • ❌ 刷新 OAuth 令牌。

先決條件:建立 Google Cloud 項目

我們將建立一個小型社交項目,允許使用者透過 Google 進行身份驗證。為此,您必須建立 Google 應用程式。

先建立一個新的 Google Cloud 項目,然後為該項目配置 OAuth 同意畫面。將使用者類型設定為外部,然後啟用以下範圍:

  • .../auth/userinfo.email
  • .../auth/userinfo.profile

設定同意畫面後,透過造訪 Google Cloud 憑證頁面建立 OAuth 2.0 用戶端 ID。保留客戶端ID客戶端密鑰:我們稍後將在專案中使用它們。

使用 Socialite 設定一個最小的 Laravel 項目

建立一個新的 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',
],
登入後複製

此文件中的新程式碼實作了以下路由:

  • 重定向到 Google 以使用適當的資訊進行社交登入。
  • 處理來自 Google 的回呼。此路由在登入時建立或更新用戶,然後對他們進行身份驗證,並將他們重定向到主頁。
  • 註銷經過驗證的使用者。

最後,將 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 的部落格文章和論壇貼文。我想對其中的一些人表示感謝。

  • 我如何為 Laravel Socialite 支援的應用程式編寫整合測試,作者:Stefan Zweifel
  • ServerSideUp 論壇:社群名流最佳實踐,對話
  • Stack Overflow:如何測試 Laravel Socialite
  • Stack Exchange:連結或不連結社交登入與符合的電子郵件
  • Stack Exchange:處理關聯的社交帳戶和潛在的孤兒

如果您有興趣深入挖掘,請閱讀這些內容。另外,如果您對本文的第 2 部分感興趣,請告訴我,我將深入探討處理多個社交提供者、處理使用者更改電子郵件地址或處理刷新權杖。

以上是在 Laravel 中實作和測試社交名流身份驗證的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:dev.to
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板