Laravel Sanctum多子域SPA认证问题求助
问题分析与解决方案
核心问题根源
当前认证逻辑混淆了会话式认证(Inertia后台)和Token式认证(Nuxt3前端),加上跨域会话共享配置冲突,导致一系列认证异常。
具体问题解决步骤
1. 修复跨域会话与Sanctum配置
当前SESSION_DOMAIN=.kpowa.dev会让后台和前端共享同一会话,这是导致"后台登录后前端登录返回305、前端登录后后台仍显示登录"的直接原因。需调整配置实现前后端认证独立:
修改.env配置
# 仅后台域名作为会话式认证的状态域 SANCTUM_STATEFUL_DOMAINS="admin.kpowa.dev" # 后台会话独立,不共享给前端 SESSION_DOMAIN=admin.kpowa.dev # 单独声明前端API允许的域名 SANCTUM_API_DOMAINS="app.kpowa.dev,app.kpowa.dev:80"
调整Sanctum配置文件(config/sanctum.php)
找到stateful项,修改为:
'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'admin.kpowa.dev')),
确保后台的会话认证仅对admin域名生效,不干扰前端。
2. 分离前后端认证逻辑
当前store方法同时处理两种认证类型,逻辑混乱,需拆分路由与控制器方法:
拆分登录路由
在routes/api.php中定义前端专属API路由:
// 前端API登录(仅接受JSON请求) Route::post('/login', [AuthController::class, 'apiLogin'])->middleware('throttle:api'); // 前端获取用户信息(需Token认证) Route::get('/user', function (Request $request) { return $request->user(); })->middleware('auth:sanctum');
在routes/web.php中保留后台Inertia的登录路由:
// 后台Inertia登录 Route::post('/login', [AuthController::class, 'webLogin'])->middleware('guest');
重写认证控制器方法
新增apiLogin方法(处理Nuxt3前端的Token认证)
public function apiLogin(LoginRequest $request): JsonResponse { $validated = $request->validated(); $user = User::where('username', $validated['username'])->first(); if (!$user || !Hash::check($validated['password'], $user->password)) { return response()->json(['error' => trans('auth.failed')], 422); } // 生成前端专属API Token,便于后续管理 $token = $user->createToken('nuxt-api-token')->plainTextToken; return response()->json([ 'token' => $token, 'user' => $user ], 200); }
保留webLogin方法(处理后台Inertia的会话认证)
public function webLogin(LoginRequest $request): RedirectResponse|JsonResponse { $credentials = $request->only('username', 'password') + ['type' => 1]; try { $request->authenticate($credentials); $request->session()->regenerate(); return redirect()->intended(RouteServiceProvider::HOME); } catch (\Exception $e) { return back()->withErrors(['error' => trans('auth.failed')]); } }
调整LoginRequest的authenticate方法
移除冗余逻辑,专注会话认证:
public function authenticate(array $credentials): void { $this->ensureIsNotRateLimited(); if (! Auth::attempt($credentials, $this->boolean('remember'))) { RateLimiter::hit($this->throttleKey()); throw ValidationException::withMessages([ 'error' => trans('auth.failed'), ]); } RateLimiter::clear($this->throttleKey()); }
3. 修复Nuxt3前端的认证请求
前端需正确携带Token访问API:
- 登录成功后,将返回的
token存入本地存储(如localStorage) - 后续所有API请求,在请求头添加
Authorization: Bearer {token} - 确保请求的
Content-Type为application/json,避免触发Laravel的会话认证逻辑
4. 解决305重定向问题
拆分路由后,前端请求走/api/login(无会话中间件),不会再触发后台已登录状态下的重定向逻辑。
验证效果
- 登录后台后,前端访问
/api/login可正常登录,无305响应 - 前端登录后,携带Token调用
/api/user将返回用户数据,无401错误 - 前后端登录状态完全独立,一方退出不影响另一方
内容的提问来源于stack exchange,提问作者Yeasir Arafat
相关产品推荐
相关产品推荐

