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

Nuxt向Laravel Sanctum发送POST请求跳转至登录页问题排查

问题:Laravel 8 + Sanctum + Nuxt POST请求被中间件拦截,仅GET请求正常

问题现象

  • 技术栈:Laravel 8 + Sanctum,前端为最新版Nuxt
  • GET接口全部可正常工作,但POST请求提交表单时被中间件拦截:
    • 使用API路由时,\Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class会触发跳转到后台登录页
    • 使用Web路由时,\App\Http\Middleware\EncryptCookies::class同样触发登录页跳转
  • 注释上述两个中间件后,POST请求可正常执行;Postman测试无跳转问题,仅Nuxt的fetch请求出现异常
  • 已成功从sanctum获取XSRF-TOKEN并存入Application Cookie,但POST请求仍失败,终端提示:Closed without sending a request; it was probably just an unused speculative preconnection

相关配置

cors.php

'paths' => ['*'],

'allowed_methods' => ['*'],

'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:3000')],

'allowed_origins_patterns' => [],

'allowed_headers' => ['*'],

'exposed_headers' => [],

'max_age' => 0,

'supports_credentials' => true,

.env

APP_URL=http://localhost:8000
FRONTEND_URL=http://localhost:3000

SESSION_DOMAIN=.localhost
SESSION_SECURE_COOKIE=false

SANCTUM_STATEFUL_DOMAINS=127.0.0.1:8000,localhost:3000,localhost

nuxt.config.ts

routeRules: {
  '/api/**': {
    proxy: { to: "http://localhost:8000/api/**" },
  },

  '/sanctum/**': {
    proxy: { to: "http://localhost:8000/sanctum/**" },
  }
}

前端代码示例

表单提交函数

async function sendForm(){
    if(form.value.email_honeypot == ''){
        form.value.email_honeypot = props.data.honey;

        await useFetch('/sanctum/csrf-cookie', { credentials: 'include' });
        const token = useCookie('XSRF-TOKEN')
        form.value._token = token.value;

        formData.value.errors = {};
        const { data: responseData, error, status } = await useCustomFetch('/api/forms-plugin/1/submit', { method: "POST", watch: false, body: form.value, headers: { Accept: 'application/json', 'X-XSRF-TOKEN': token.value }})
        formData.value.response = responseData;

        if(responseData.value.errors) {
            for (const key in responseData.value.errors) {
                const parts = key.split('.');
                const fieldId = parseInt(parts[1]);
                formData.value.errors[fieldId] = responseData.value.errors[key][0];
            }
        }

        if(responseData.value.message) {
            formData.value.success = true;
        }

        form.value.email_honeypot = '';
    }
}

自定义Fetch封装

import type { UseFetchOptions } from 'nuxt/app'
import { defu } from 'defu'

export function useCustomFetch<T> (url: string, options: UseFetchOptions<T> = {}) {
    const config = useRuntimeConfig()

    const defaults: UseFetchOptions<T> = {
        baseURL: config.public.baseUrl,
        // cache request - causes trouble with url
        // key: url,

        // set user token if connected
        headers: {
            Authorization: `Bearer ${config.public.accessToken}`,
            Accept: 'application/json',
        },

        credentials: 'include',

        onResponse (_ctx) {
            // _ctx.response._data = new myBusinessResponse(_ctx.response._data)
        },

        onResponseError (_ctx) {
            // throw new myBusinessError()
        }
    }

    // for nice deep defaults, please use unjs/defu
    const params = defu(options, defaults)

    return useFetch(url, params)
}

需求

在保留EnsureFrontendRequestsAreStateful::class中间件的前提下,实现POST请求正常执行。

内容的提问来源于stack exchange,提问作者Daniel Kužela

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 18:55:57