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同样触发登录页跳转
- 使用API路由时,
- 注释上述两个中间件后,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
相关产品推荐
相关产品推荐

