使用axios或fetch无法发送httpOnly cookie,next-auth获取session为null
解决方案
现象说明
浏览器直接访问路由正常是因为浏览器会自动携带当前域名下所有符合条件的Cookie,且不会触发跨域预检校验,所以可以正常获取会话。
排查&修复步骤
1. 配置正确的CORS规则
如果前端运行端口与Next.js服务端口(默认3000)不一致,必须在API路由中显式配置CORS头,禁止使用*作为允许源:
export default async function handler(req, res) { // 新增CORS配置 res.setHeader('Access-Control-Allow-Credentials', 'true'); // 替换为你前端实际的访问地址,如http://localhost:5173 res.setHeader('Access-Control-Allow-Origin', 'http://localhost:你的前端端口'); res.setHeader('Access-Control-Allow-Methods', 'GET,OPTIONS,POST,PUT,DELETE'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type,X-CSRF-Token'); // 处理OPTIONS预检请求 if (req.method === 'OPTIONS') { return res.status(200).end(); } const session = await getSession({ req }); if (!session) { return res.status(401).json({ error: 'Unauthorized' }); } // 后续业务逻辑 }
2. 修正next-auth Cookie配置
检查pages/api/auth/[...nextauth].js中的Cookie配置,本地开发环境不要强制开启secure属性(仅HTTPS环境生效),跨子域访问需要补充domain配置:
export default NextAuth({ // 你的其他next-auth配置,如providers、secret等 cookies: { sessionToken: { name: process.env.NODE_ENV === 'production' ? '__Secure-next-auth.session-token' : 'next-auth.session-token', path: '/', httpOnly: true, sameSite: 'lax', // 仅生产环境开启secure,本地http环境开启后Cookie不会被浏览器存储 secure: process.env.NODE_ENV === 'production', // 跨子域访问时补充,如 domain: '.your-domain.com' }, }, })
3. 服务端发起请求需手动透传Cookie
如果axios请求是在Next.js服务端(getServerSideProps、服务端组件、其他API路由内部)发起的,withCredentials配置不生效,需要手动将当前请求的Cookie头透传给目标API:
// 示例:在getServerSideProps中发起请求 export async function getServerSideProps(context) { const res = await axios.get( `http://localhost:3000/api/structure/${context.params.name}`, { headers: { // 手动传递当前请求的Cookie Cookie: context.req.headers.cookie || '', } } ); return { props: { data: res.data } }; }
4. 非GET请求需携带CSRF令牌
如果你使用POST/PUT等非GET方法请求API,需要在请求头中携带next-auth生成的CSRF令牌:
import { getCsrfToken } from 'next-auth/client'; // 发起请求前先获取CSRF令牌 const csrfToken = await getCsrfToken(); const res = await axios.post( 'http://localhost:3000/api/xxx', { data: xxx }, { withCredentials: true, headers: { 'X-CSRF-Token': csrfToken } } );
内容的提问来源于stack exchange,提问作者Med El Mobarik
相关产品推荐
相关产品推荐

