You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何配置Laravel Passport实现多种认证方式返回JWT?

Laravel Passport 多认证逻辑优化方案

针对你在Laravel 10+Octane+Spatie多租户环境下,用Passport搭建认证服务时遇到的模型依赖注入问题,以及后续扩展多种登录方式的需求,以下是几种合理的解决方案:

一、自定义 AccessTokenController(优先推荐)

这种方案能完全接管Passport的令牌发放流程,自然实现依赖注入,同时方便后续扩展SSO、令牌登录等多种认证方式。

实现步骤:

  1. 复制Passport默认的AccessTokenController代码到自定义控制器(例如App\Http\Controllers\Auth\CustomAccessTokenController),原控制器路径为Laravel\Passport\Http\Controllers\AccessTokenController。
  2. 在自定义控制器构造函数中注入所需的认证服务(如UserAuthenticator),替代模型中app()->make的写法:
    use App\Services\UserAuthenticator;
    use Illuminate\Http\Request;
    use Laravel\Passport\Client;
    
    class CustomAccessTokenController extends Controller
    {
        protected $authenticator;
    
        public function __construct(UserAuthenticator $authenticator)
        {
            $this->authenticator = $authenticator;
            $this->middleware('throttle');
        }
    
        public function issueToken(Request $request)
        {
            // 保留Passport原有参数验证逻辑
            $request->validate([
                'grant_type' => 'required|string',
                'client_id' => 'required|string',
                'client_secret' => 'required|string',
                'username' => 'required|string',
                'password' => 'required|string',
                'scope' => 'nullable|string',
            ]);
    
            // 通过注入的服务验证用户凭证
            $user = $this->authenticator->validateCredentials($request->username, $request->password);
    
            if (!$user) {
                return response()->json(['error' => 'invalid_credentials'], 401);
            }
    
            // 获取租户对应的Password Grant Client
            $client = Client::where('tenant_id', tenant()->id)
                ->where('password_client', true)
                ->firstOrFail();
    
            // 生成令牌并添加自定义Claims
            $token = $user->createToken('Password Grant Token', [], now()->addMinutes(60));
            $token->accessToken->forceFill([
                'payload' => array_merge($token->accessToken->payload, [
                    'tenant_id' => tenant()->id,
                    // 按需添加其他自定义Claims
                ])
            ])->save();
    
            return response()->json([
                'access_token' => $token->accessToken,
                'token_type' => 'Bearer',
                'expires_in' => $token->token->expires_at->diffInSeconds(now()),
                'refresh_token' => $token->refreshToken,
            ]);
        }
    }
    
  3. 替换Passport默认路由,在routes/web.php中使用自定义控制器:
    Route::post('/oauth/token', [\App\Http\Controllers\Auth\CustomAccessTokenController::class, 'issueToken']);
    

优缺点:

  • 优点:完全掌控认证流程,依赖注入规范,便于后续扩展多种登录方式,适配微服务认证中心的长期迭代需求。
  • 缺点:需要维护Passport核心逻辑的副本,Passport版本升级时需同步代码差异。

二、自定义 UserProvider(适合复杂凭证验证场景)

如果不同租户或登录方式的用户来源、验证逻辑差异较大,可以通过自定义UserProvider将认证逻辑从模型中剥离,符合单一职责原则。

实现步骤:

  1. 创建自定义UserProvider,继承EloquentUserProvider并注入认证服务:
    namespace App\Auth;
    
    use App\Services\UserAuthenticator;
    use Illuminate\Auth\EloquentUserProvider;
    use Illuminate\Contracts\Auth\Authenticatable;
    
    class TenantUserProvider extends EloquentUserProvider
    {
        protected $authenticator;
    
        public function __construct($hasher, $model, UserAuthenticator $authenticator)
        {
            parent::__construct($hasher, $model);
            $this->authenticator = $authenticator;
        }
    
        // 重写根据凭证获取用户的方法
        public function retrieveByCredentials(array $credentials)
        {
            $model = $this->createModel();
            return $model->where('username', $credentials['username'])
                ->where('tenant_id', tenant()->id)
                ->first();
        }
    
        // 重写验证凭证的方法
        public function validateCredentials(Authenticatable $user, array $credentials)
        {
            return $this->authenticator->validate($user, $credentials['password']);
        }
    }
    
  2. 在AuthServiceProvider中注册自定义Provider:
    public function boot()
    {
        $this->registerPolicies();
    
        Auth::provider('tenant-user', function ($app, array $config) {
            return new \App\Auth\TenantUserProvider(
                $app['hash'],
                $config['model'],
                $app->make(UserAuthenticator::class)
            );
        });
    }
    
  3. 修改config/auth.php配置,使用自定义Provider:
    'guards' => [
        'api' => [
            'driver' => 'passport',
            'provider' => 'tenant-users',
        ],
    ],
    'providers' => [
        'tenant-users' => [
            'driver' => 'tenant-user',
            'model' => App\Models\User::class,
        ],
    ],
    

优缺点:

  • 优点:符合Laravel认证体系设计,逻辑分离清晰,适合多用户类型、复杂凭证验证场景。
  • 缺点:需要熟悉Laravel UserProvider机制,对新手有一定门槛。

三、不推荐的方案:静态方法/app()->make

直接在User模型中使用静态方法或app()->make获取服务,虽然能临时解决问题,但违背依赖注入原则,代码耦合度高,难以测试和维护。尤其在Octane环境下,静态方法可能引发状态残留问题,不建议长期使用。


内容的提问来源于stack exchange,提问作者WellBloud

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 08:32:27