同主机下Laravel Sanctum会话认证在Next.js服务端未授权问题
问题解决:Next.js服务端getServerSideProps请求Laravel Sanctum未授权
核心问题分析
客户端请求正常但服务端请求失败,本质是服务端环境下无法自动读取和传递Sanctum所需的会话Cookie与CSRF Token,同时存在代码引用错误和配置遗漏。
分步解决方案
1. 修复Axios实例引用错误
你的getServerSideProps中使用了未定义的ax.post,需替换为你创建的axiosInstance.post:
// 错误写法 // const response = await ax.post(...) // 正确写法 const response = await axiosInstance.post(...)
2. 服务端手动处理CSRF Token
服务端无法直接访问浏览器Cookie,需从请求头中解析Cookie并手动添加X-XSRF-TOKEN请求头:
首先安装Cookie解析工具:
npm install cookie
然后修改getServerSideProps:
import { parse } from 'cookie'; export async function getServerSideProps(context) { const { query, req } = context; const { page, search_term, nip, tableName } = query; // 解析请求头中的Cookie const cookies = parse(req.headers.cookie || ''); const xsrfToken = cookies['XSRF-TOKEN']; try { const response = await axiosInstance.post( `api/v1/admin/${tableName}`, { page: page, search_term: search_term, nip: nip || 10 }, { withCredentials: true, headers: { Cookie: req.headers.cookie, // 解码并添加CSRF Token请求头 'X-XSRF-TOKEN': xsrfToken ? decodeURIComponent(xsrfToken) : '', } } ); return { props: { initItems: response.data.data, initMeta: response.data.meta, initSearchTerm: search_term || '', iniNip: nip || 10 } }; } catch (err) { console.log(err); return { notFound: true }; } }
3. 调整Axios拦截器适配服务端
原拦截器依赖浏览器Cookie API,服务端环境下会失效,需添加服务端判断逻辑:
const onRequest = (config) => { // 服务端环境直接跳过CSRF Token预获取 if (typeof window === 'undefined') { return config; } if ( (config.method === 'post' || config.method === 'put' || config.method === 'delete') && !Cookies.get('XSRF-TOKEN') ) { return setCSRFToken().then(response => config); } return config; };
4. 验证Laravel配置正确性
确保Laravel后端允许跨域凭证传递并包含Next.js域名:
- config/cors.php:
return [ 'paths' => ['api/*', 'sanctum/csrf-cookie'], 'allowed_methods' => ['*'], 'allowed_origins' => ['http://localhost:3000'], // 你的Next.js地址 'allowed_headers' => ['*'], 'supports_credentials' => true, // 必须开启 ];
- config/sanctum.php:
return [ 'stateful' => explode(',', env('SANCTUM_STATEFUL_DOMAINS', 'localhost,localhost:3000,127.0.0.1:8000')), ];
- .env:
SESSION_DOMAIN=localhost SANCTUM_STATEFUL_DOMAINS=localhost:3000,localhost:8000
内容的提问来源于stack exchange,提问作者Esmaeil Soomari
相关产品推荐
相关产品推荐

