Laravel Passport认证问题:Vue请求提示Unauthenticated求助
你的核心问题出在路由中间件的认证方式不匹配:VK机器人用的是auth:api中间件对应的Bearer令牌认证逻辑,而Vue端依赖的是Laravel Web端的CSRF+Session认证体系,两种逻辑不兼容,所以Vue请求会被auth:api中间件拦截。
下面给你几个针对性的解决方案:
方案1:拆分路由,分别适配两种认证方式
这是最清晰易维护的做法,把给Vue的路由和给机器人的路由分开,各自使用对应的认证中间件:
1.1 配置Web路由(给Vue用)
在routes/web.php里定义Vue需要调用的路由,使用默认的auth中间件(基于Session认证):
Route::middleware('auth')->group(function(){ Route::get('/prepare/', 'CompgenApiController@prepareDefault'); Route::post('/replace/', 'CompgenApiController@replace'); // 其他需要Vue访问的路由 });
1.2 配置API路由(给VK机器人用)
在routes/api.php里保留机器人的路由,继续使用auth:api中间件:
Route::middleware('auth:api')->group(function(){ Route::get('/prepare/', 'CompgenApiController@prepareDefault'); Route::post('/replace/', 'CompgenApiController@replace'); // 其他需要机器人访问的路由 });
这样Vue端的请求走Web路由(带CSRF令牌和Session Cookie),机器人走API路由(带Bearer令牌),各自适配对应的认证逻辑,不会冲突。
方案2:自定义中间件,同时支持两种认证方式
如果不想拆分路由,希望同一个路由同时兼容Session和Bearer令牌认证,可以自定义一个中间件:
2.1 创建自定义认证中间件
在终端执行命令生成中间件:
php artisan make:middleware AuthenticateBoth
打开app/Http/Middleware/AuthenticateBoth.php,修改内容为:
<?php namespace App\Http\Middleware; use Illuminate\Auth\Middleware\Authenticate as Middleware; class AuthenticateBoth extends Middleware { protected function authenticate($request, array $guards) { // 先尝试API令牌认证(适配机器人) if ($this->auth->guard('api')->check()) { return $this->auth->shouldUse('api'); } // 再尝试Session认证(适配Vue) if ($this->auth->guard('web')->check()) { return $this->auth->shouldUse('web'); } // 两种认证都失败时返回未认证 $this->unauthenticated($request, $guards); } }
2.2 注册中间件
打开app/Http/Kernel.php,在$routeMiddleware数组里添加:
protected $routeMiddleware = [ // 其他中间件... 'auth.both' => \App\Http\Middleware\AuthenticateBoth::class, ];
2.3 路由使用自定义中间件
把原来的路由中间件换成auth.both:
Route::middleware('auth.both')->group(function(){ Route::get('/prepare/', 'CompgenApiController@prepareDefault'); Route::post('/replace/', 'CompgenApiController@replace'); });
方案3:确保Vue端请求配置正确
如果选择方案1的Web路由,还要保证Vue的请求正确携带Session和CSRF令牌:
在Vue项目的请求配置(比如axios)里添加:
// 确保携带Cookie(Session认证依赖) axios.defaults.withCredentials = true; // 设置CSRF令牌 axios.defaults.headers.common['X-CSRF-TOKEN'] = document.querySelector('meta[name="csrf-token"]').content;
同时要检查Laravel的.env文件里SESSION_DOMAIN配置是否正确(同域场景可留空或填写当前域名),如果是跨域场景,还要配置CORS允许携带Credentials。
内容的提问来源于stack exchange,提问作者Viktor

