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对应的模型无邮箱验证逻辑),如果需要针对不同守卫做差异化校验,建议使用自定义中间件。
方式二:自定义中间件(适配复杂场景)
如果需要更灵活的认证逻辑(比如不同守卫对应不同附加校验),可以创建自定义中间件实现“任意守卫通过即认证”:
- 生成自定义中间件
php artisan make:middleware AuthenticateWithAnyGuard
- 编写中间件逻辑
编辑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); } }
- 注册中间件
在app/Http/Kernel.php的$routeMiddleware数组中添加:
protected $routeMiddleware = [ // ... 其他中间件 'auth.any' => \App\Http\Middleware\AuthenticateWithAnyGuard::class, ];
- 使用自定义中间件定义路由
// 支持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
相关产品推荐
相关产品推荐

