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

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(无会话中间件),不会再触发后台已登录状态下的重定向逻辑。


验证效果

  1. 登录后台后,前端访问/api/login可正常登录,无305响应
  2. 前端登录后,携带Token调用/api/user将返回用户数据,无401错误
  3. 前后端登录状态完全独立,一方退出不影响另一方

内容的提问来源于stack exchange,提问作者Yeasir Arafat

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 15:43:13