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

Laravel多认证守卫下公共API路由配置问题求助

多Passport守卫下的API路由多认证支持方案

问题场景

我在应用中配置了多个基于Passport的认证守卫:

'api' => [
    'driver' => 'passport',
    'provider' => 'users',
    'hash' => false,
],

'api-customer' => [
    'driver' => 'passport',
    'provider' => 'customers',
    'hash' => false,
],

'api-manufacturer' => [
    'driver' => 'passport',
    'provider' => 'manufacturers',
    'hash' => false,
],

现有公共API路由bids/job/update-quote需要同时允许api和api-manufacturer守卫的用户访问。此前的路由定义方式存在问题:

Route::middleware('auth:api', 'verified')->group( function () {
    Route::post('bids/job/update-quote', 'BidController@updateOrCreateQuote');
});
Route::middleware('auth:api-manufacturer')->group(function () {
    Route::post('bids/job/update-quote', 'BidController@updateOrCreateQuote');
});

上述代码中只有第二个路由生效;尝试middleware(['auth:api', 'auth:api-manufacturer'])时,又会要求同时通过两个守卫的认证,不符合“二选一”的需求。

正确实现方案

方式一:利用Laravel原生auth中间件的多守卫“或”逻辑

Laravel的auth中间件支持将多个守卫用逗号分隔作为单个参数传入,此时会采用任意一个守卫通过即认证成功的逻辑,而非同时验证所有守卫。

修改路由定义如下:

Route::middleware(['auth:api,api-manufacturer', 'verified'])->group(function () {
    Route::post('bids/job/update-quote', 'BidController@updateOrCreateQuote');
});

注意:verified中间件仅对api守卫关联的模型生效(若api-manufacturer对应的模型无邮箱验证逻辑),如果需要针对不同守卫做差异化校验,建议使用自定义中间件。

方式二:自定义中间件(适配复杂场景)

如果需要更灵活的认证逻辑(比如不同守卫对应不同附加校验),可以创建自定义中间件实现“任意守卫通过即认证”:

  1. 生成自定义中间件
php artisan make:middleware AuthenticateWithAnyGuard
  1. 编写中间件逻辑
    编辑app/Http/Middleware/AuthenticateWithAnyGuard.php:
<?php

namespace App\Http\Middleware;

use Illuminate\Auth\Middleware\Authenticate as Middleware;

class AuthenticateWithAnyGuard extends Middleware
{
    protected function authenticate($request, array $guards)
    {
        if (empty($guards)) {
            $guards = [null];
        }

        // 遍历所有指定守卫,只要有一个通过认证就设置为默认守卫并返回
        foreach ($guards as $guard) {
            if ($this->auth->guard($guard)->check()) {
                $this->auth->setDefaultDriver($guard);
                return;
            }
        }

        // 所有守卫都未通过时,返回未认证响应
        $this->unauthenticated($request, $guards);
    }
}
  1. 注册中间件
    在app/Http/Kernel.php的$routeMiddleware数组中添加:
protected $routeMiddleware = [
    // ... 其他中间件
    'auth.any' => \App\Http\Middleware\AuthenticateWithAnyGuard::class,
];
  1. 使用自定义中间件定义路由
// 支持api和api-manufacturer任意一个守卫访问
Route::middleware(['auth.any:api,api-manufacturer', 'verified'])->group(function () {
    Route::post('bids/job/update-quote', 'BidController@updateOrCreateQuote');
});

// 后续管理员路由可直接复用该中间件
Route::middleware(['auth.any:api,admin-api'])->group(function () {
    // 管理员专属路由
});

问题原因说明

  • 重复定义同路径路由时,Laravel会以最后注册的路由为准,因此第二个路由覆盖了第一个。
  • 拆分多个auth:中间件时,Laravel会要求同时通过所有守卫的认证(“与”逻辑),不符合“二选一”的需求。

内容的提问来源于stack exchange,提问作者Yusuf ÇAKIRCA

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 11:48:19