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

相关推荐
Go高并发架构_王工18 小时前
Kafka简介:了解现代分布式消息队列的基石
分布式·后端·kafka
IT_陈寒18 小时前
Redis 7.0 性能优化实战:5个让我降低50%内存占用的核心技巧
前端·人工智能·后端
智商偏低18 小时前
ABP 框架中的 HttpContextWebClientInfoProvider
后端·asp.net
颜酱18 小时前
用填充表格法吃透01背包及其变形-3
前端·后端·算法
明月_清风18 小时前
Node.js 事件循环(Event Loop)详解
前端·后端
最贪吃的虎19 小时前
【分布式】分布式事务框架 Seata 详解:架构与四种实现模式
java·开发语言·数据库·分布式·后端·架构
悟空码字19 小时前
Spring Boot 打包部署,JAR vs WAR
java·spring boot·后端
颜酱19 小时前
用填充表格法吃透01背包及其变形-2
前端·后端·算法
爬山算法19 小时前
Hibernate(24)Hibernate如何实现乐观锁?
java·后端·hibernate
Mars酱19 小时前
1分钟了解响应式编程 | dubbo框架下响应式官例
java·后端·rxjava