Next.js 13服务端渲染中Axios withCredentials失效问题求助
问题根源
SSG(静态站点生成)是在项目构建阶段预渲染页面,这个过程完全没有用户的请求上下文——你的浏览器Cookie存在用户本地,构建服务器根本拿不到,自然没法携带给Laravel接口,导致401未授权。而且Laravel Sanctum的认证依赖用户会话Cookie,SSG阶段本身就不存在用户会话,所以这类需要用户登录状态的页面,本身就不适合用SSG。
下面给你两个可行的解决方案:
方案一:改用SSR(服务器端渲染)传递Cookie
在Next.js 13 App Router中,页面默认是服务器组件,可以直接获取当前请求的Cookie,手动传递给Laravel接口:
- 修改接口服务,支持接收Cookie参数:
// CategoryService.js import axios from 'axios'; const baseURL = process.env.NEXT_PUBLIC_API_URL; export const getAll = async (cookie) => { return axios.get(`${baseURL}/categories`, { headers: { // 手动把请求Cookie传给Laravel Cookie: cookie, }, withCredentials: true, }); };
- 在页面组件中获取请求Cookie并调用接口:
// app/categories/page.js import { headers } from 'next/headers'; import CategoryService from '@/services/CategoryService'; import CategoryView from '@/components/CategoryView'; export default async function Page() { // 从当前请求头中拿到Cookie const requestHeaders = headers(); const cookie = requestHeaders.get('cookie'); const response = await CategoryService.getAll(cookie); const categories = response.data.data; return <CategoryView categories={categories} />; }
注:这个页面会自动变成SSR模式(每次用户请求时渲染),不再是SSG,这样才能拿到当前用户的会话Cookie。
方案二:静态页面+客户端请求数据
如果必须保留页面的静态特性,把需要认证的数据请求放到客户端组件中,利用浏览器环境自动携带Cookie:
- 创建客户端组件处理数据请求:
// app/categories/CategoryClient.js 'use client'; import { useEffect, useState } from 'react'; import CategoryService from '@/services/CategoryService'; import CategoryView from '@/components/CategoryView'; export default function CategoryClient() { const [categories, setCategories] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { const fetchData = async () => { try { // 客户端环境下,Axios的withCredentials会自动携带Cookie const response = await CategoryService.getAll(); setCategories(response.data.data); } catch (err) { // 处理未授权,比如跳转到登录页 if (err.response?.status === 401) { window.location.href = '/login'; } } finally { setLoading(false); } }; fetchData(); }, []); if (loading) return <div>加载中...</div>; return <CategoryView categories={categories} />; }
- 在静态页面中引入这个客户端组件:
// app/categories/page.js import CategoryClient from './CategoryClient'; export default function Page() { // 这里可以放静态内容,动态数据由客户端组件加载 return <CategoryClient />; }
额外注意事项
- 确保Laravel的
config/cors.php中,allowed_origins包含你的Next.js域名,supports_credentials设为true; - 如果Next.js和Laravel不在同一域名,要配置Laravel的Cookie
domain参数,保证Cookie可以跨域传递; - 永远不要尝试在SSG构建阶段获取用户专属数据——SSG生成的页面是所有用户共用的,不可能包含私有内容。
内容的提问来源于stack exchange,提问作者Juan Pablo B
相关产品推荐
相关产品推荐

