Laravel 扩展 Auth Guard 实现自定义身份验证

前言

最近需要实现一个功能,需要对接基于 Cookie 的 SSO 方案,用户登录成功后,身份验证中心会在用户的浏览器中设置一个特定域下的 Cookie,用于标识用户的身份。其他需要集成SSO的应用程序在接收到请求时,会检查浏览器中是否存在该特定域下的 Cookie,并使用其中的用户身份信息进行认证和授权。

在 Laravel 框架中默认有提供身份验证(Authentication)服务,并且通过服务容器(Service Container)管理,从而使你能够轻松地替换、扩展和管理。

Laravel 身份验证体系

在开始自定义 Auth Guard 之前,首先需要理解 Laravel 的身份验证体系。Laravel 的身份验证部分已经被抽象出来,它提供了 Guard 和 Provider 的概念来处理用户认证:

  • Guard 负责认证请求中的用户,通常与特定的用户身份相关联(例如,通过会话或令牌)。
  • Provider 负责从持久化存储(如数据库)中检索用户信息。

Laravel 提供了几个内置的 Guard,包括 Session Guard、Token Guard 和 JWT Guard 等。每个 Guard 都有对应的 Provider,以便获取用户信息。

创建自定义 Guard

要创建自定义 Guard,首先需要创建一个新的 Guard 类并实现Illuminate\Contracts\Auth\Guard接口。Auth 有提供两个 Guard 接口,分别是 Guard 和 StatefulGuard,顾名思义 StatefulGuard 比 Guard 多了状态能力,因为基于 Cookie 的 SSO 方案,不需要有自己的状态,所以我选择了 Guard 接口去实现。

php 复制代码
<?php

namespace App\Auth;

use App\Services\SSOService;
use Illuminate\Auth\GuardHelpers;
use Illuminate\Contracts\Auth\Guard;
use Illuminate\Contracts\Auth\UserProvider;
use Illuminate\Http\Request;

class SSOGuard implements Guard
{
    use GuardHelpers;

    public function __construct(
        private readonly Request $request,
        private readonly UserProvider $userProvider
    ) {
    }

    public function user()
    {
        if (!is_null($this->user)) {
            return $this->user;
        }

        $user = null;

        $userInfo = SSOService::getUserInfo($this->request->cookie('TOKEN'));

        if ($userInfo) {
            $this->user = $this->userProvider->retrieveByCredentials(['id' => $user->id]);
        }

        return $this->user;
    }

    public function validate(array $credentials = [])
    {
        // 因为不需要使用 validate 方法所以直接返回 false,如果需要自行补充对应方法内容
        return false;
    }
}

注册自定义 Guard

接下来需要AppServiceProvider扩展 Auth Guard:

php 复制代码
class AppServiceProvider extends ServiceProvider
{
    /**
     * Register any application services.
     */
    public function register(): void
    {
        // ...
    }

    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        Auth::extend('sso', function (Application $app, string $name, array $config) {
            return new SSOGuard(request(), Auth::createUserProvider($config['provider']));
        });
    }
}

配置自定义 Guard

config/auth.php 文件添加新的guard:

php 复制代码
'guards' => [
    'sso-auth' => [
        'driver' => 'sso',
        'provider' => 'users',
    ],
],

使用自定义 Guard

完成了自定义 Guard 的创建、注册、配置,就可以在应用程序中使用它了。可以通过 auth()->guard('sso-auth') 方法来获取自定义 Guard 的实例,并使用其提供的方法进行用户认证和授权。

结论

通过自定义 Laravel 的 Auth Guard,我们能够根据项目需求灵活地定制身份验证和授权功能。特别是将身份验证逻辑写在 Auth Guard 中,能够使代码更加专注和模块化。这样做的好处在于,身份验证逻辑与其他业务逻辑得以分离,从而提高了代码的可维护性和可扩展性。这种分离使得我们能够更清晰地理解和管理身份验证的相关功能,同时也更容易进行测试和调试。

参考资料

laravel.com/docs/11.x/a...

相关推荐
man20171 小时前
【2024最新】基于springboot+vue的闲一品交易平台lw+ppt
vue.js·spring boot·后端
hlsd#1 小时前
关于 SpringBoot 时间处理的总结
java·spring boot·后端
路在脚下@1 小时前
Spring Boot 的核心原理和工作机制
java·spring boot·后端
幸运小圣2 小时前
Vue3 -- 项目配置之stylelint【企业级项目配置保姆级教程3】
开发语言·后端·rust
前端SkyRain3 小时前
后端Node学习项目-用户管理-增删改查
后端·学习·node.js
提笔惊蚂蚁3 小时前
结构化(经典)软件开发方法: 需求分析阶段+设计阶段
后端·学习·需求分析
老猿讲编程3 小时前
Rust编写的贪吃蛇小游戏源代码解读
开发语言·后端·rust
黄小耶@3 小时前
python如何使用Rabbitmq
分布式·后端·python·rabbitmq
宅小海4 小时前
Scala-List列表
开发语言·后端·scala
蔚一5 小时前
Javaweb—Ajax与jQuery请求
前端·javascript·后端·ajax·jquery