Laravel已登录用户发起ajax请求调用API返回401未认证如何解决
问题根因
默认Laravel框架的web路由组使用Session会话做身份认证,api路由组默认使用无状态的Token/Sanctum认证,二者默认不共享认证上下文。如果你的接口放在api路由组中,即使用户在前端页面已经登录,api组默认不会读取Session中的登录状态,就会返回401未授权错误。
解决方法
方案1:接口归到web路由组(最省事)
如果这个接口仅给web端页面调用,直接把路由定义放到routes/web.php文件中即可。web组默认自带Session、CSRF校验中间件,和现有web端登录逻辑完全打通,你当前的AJAX代码已经携带了_token参数,直接适配,不需要额外修改。
方案2:修改api路由组中间件适配Session认证
如果必须把接口放在api路由组中,需要调整API组的中间件配置,让它支持Session校验:
- 打开
app/Http/Kernel.php,找到$middlewareGroups下的api配置项,新增Session相关的中间件:
'api' => [ // 新增以下5个web组自带的中间件 \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, // 原有api中间件保留 'throttle:api', \Illuminate\Routing\Middleware\SubstituteBindings::class, ],
- 控制器中指定使用web guard做认证,修改构造方法的中间件定义:
$this->middleware('auth:web');
此时API路由会和web端共用Session中的登录状态,校验逻辑完全一致。
方案3:Sanctum适配同域认证
如果你用Laravel Sanctum做API认证,只需要做两处调整即可和web登录态打通:
- 在
config/sanctum.php的stateful配置项中加入你的业务域名 - AJAX请求新增
withCredentials参数,修改后的请求代码如下:
$.ajax({ type: "POST", url: "{{route('something.someevent')}}", xhrFields: { withCredentials: true }, data: { _token: _token }, success: function(o) { console.log(o); }, dataType: "json" });
排查点
如果修改后仍然报错,先确认两个配置:
- 路由是否放错了分组,
routes/api.php中的路由默认会加/api前缀和api中间件组 config/auth.php中defaults.guard是否为web,如果不是的话,调用auth中间件时必须手动指定auth:web
内容的提问来源于stack exchange,提问作者Miro
相关产品推荐
相关产品推荐

