搜索
首页后端开发php教程在 Laravel 中实现和测试社交名流身份验证

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 -->



    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Laravel Socialite Testing Example</title>


    <h1 id="Laravel-Socialite-Testing-Example">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


将新创建的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中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
unset()和session_destroy()有什么区别?unset()和session_destroy()有什么区别?May 04, 2025 am 12:19 AM

Thedifferencebetweenunset()andsession_destroy()isthatunset()clearsspecificsessionvariableswhilekeepingthesessionactive,whereassession_destroy()terminatestheentiresession.1)Useunset()toremovespecificsessionvariableswithoutaffectingthesession'soveralls

在负载平衡的情况下,什么是粘性会话(会话亲和力)?在负载平衡的情况下,什么是粘性会话(会话亲和力)?May 04, 2025 am 12:16 AM

stickysessensureuserRequestSarerOutedTothesMeServerForsessionDataConsisterency.1)sessionIdentificeAssificationAssigeaSsignAssignSignSuserServerServerSustersusiseCookiesorUrlModifications.2)一致的ententRoutingDirectSsssssubsequeSssubsequeSubsequestrequestSameSameserver.3)loadBellankingDisteributesNebutesneNewuserEreNevuseRe.3)

PHP中有哪些不同的会话保存处理程序?PHP中有哪些不同的会话保存处理程序?May 04, 2025 am 12:14 AM

phpoffersvarioussessionsionsavehandlers:1)文件:默认,简单的ButMayBottLeneckonHigh-trafficsites.2)Memcached:高性能,Idealforsforspeed-Criticalapplications.3)REDIS:redis:similartomemememememcached,withddeddeddedpassistence.4)withddeddedpassistence.4)databases:gelifforcontrati forforcontrati,有用

PHP中的会话是什么?为什么使用它们?PHP中的会话是什么?为什么使用它们?May 04, 2025 am 12:12 AM

PHP中的session是用于在服务器端保存用户数据以在多个请求之间保持状态的机制。具体来说,1)session通过session_start()函数启动,并通过$_SESSION超级全局数组存储和读取数据;2)session数据默认存储在服务器的临时文件中,但可通过数据库或内存存储优化;3)使用session可以实现用户登录状态跟踪和购物车管理等功能;4)需要注意session的安全传输和性能优化,以确保应用的安全性和效率。

说明PHP会话的生命周期。说明PHP会话的生命周期。May 04, 2025 am 12:04 AM

PHPsessionsstartwithsession_start(),whichgeneratesauniqueIDandcreatesaserverfile;theypersistacrossrequestsandcanbemanuallyendedwithsession_destroy().1)Sessionsbeginwhensession_start()iscalled,creatingauniqueIDandserverfile.2)Theycontinueasdataisloade

绝对会话超时有什么区别?绝对会话超时有什么区别?May 03, 2025 am 12:21 AM

绝对会话超时从会话创建时开始计时,闲置会话超时则从用户无操作时开始计时。绝对会话超时适用于需要严格控制会话生命周期的场景,如金融应用;闲置会话超时适合希望用户长时间保持会话活跃的应用,如社交媒体。

如果会话在服务器上不起作用,您将采取什么步骤?如果会话在服务器上不起作用,您将采取什么步骤?May 03, 2025 am 12:19 AM

服务器会话失效可以通过以下步骤解决:1.检查服务器配置,确保会话设置正确。2.验证客户端cookies,确认浏览器支持并正确发送。3.检查会话存储服务,如Redis,确保其正常运行。4.审查应用代码,确保会话逻辑正确。通过这些步骤,可以有效诊断和修复会话问题,提升用户体验。

session_start()函数的意义是什么?session_start()函数的意义是什么?May 03, 2025 am 12:18 AM

session_start()iscucialinphpformanagingusersessions.1)ItInitiateSanewsessionifnoneexists,2)resumesanexistingsessions,and3)setsasesessionCookieforContinuityActinuityAccontinuityAcconActInityAcconActInityAcconAccRequests,EnablingApplicationsApplicationsLikeUseAppericationLikeUseAthenticationalticationaltication and PersersonalizedContentent。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

适用于 Eclipse 的 SAP NetWeaver 服务器适配器

将Eclipse与SAP NetWeaver应用服务器集成。

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器