NextJS SSR组件跨域请求未正确携带Session Cookie问题
问题背景
开发了基于Next.js(App Router)前端、Express.js后端的应用,采用express-session实现用户认证。当前遇到的问题是:在SSR服务端组件中检查用户认证状态时,请求后端的Session Cookie未能正确携带,导致认证失败。
相关代码
服务端组件中的认证检查函数
import { cookies } from "next/headers" const getSession = async () => { const baseURL = process.env.NODE_ENV === 'development' ? 'http://localhost:80' : 'https://backend.com' const url = `${baseURL}/auth/authenticated` try { const response = await fetch(url, { method: 'GET', headers: { Cookie: cookies().toString() }, credentials: 'include' }) if (!response.ok) { return { authenticated: false } } return { authenticated: true} } catch (error) { return { authenticated: false } } }
服务端组件使用示例
export default async function Profile() { const { authenticated } = await getSession() if(!authenticated) { redirect('/') } else { return ( <section className="w-full"> <ProfilePage /> </section> ) } }
Express后端CORS与Session配置
app.use(cors({ origin: process.env.NODE_ENV === "production" ? 'https://frontend.vercel.app' : 'http://localhost:3000', credentials: true })) app.use(session({ store: sessionStore, secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: true, cookie: { secure: process.env.NODE_ENV === "production", sameSite: process.env.NODE_ENV === "production" ? 'none' : 'strict', httpOnly: true, domain: process.env.NODE_ENV === "production" ? 'frontend.vercel.app' : 'localhost' } }))
现象对比
生产环境下,客户端组件请求后端时,Session包含用户信息:
Session { cookie: { path: '/', _expires: null, originalMaxAge: null, httpOnly: true, partitioned: null, priority: null, secure: true, domain: frontend.vercel.app, sameSite: 'none' }, user: { id: new ObjectId('662ff092323d26bb5abd51c4') } }
而服务端组件请求后端时,Session缺失用户信息:
Session { cookie: { path: '/', _expires: null, originalMaxAge: null, httpOnly: true, secure: true, sameSite: 'none' } }
问题排查与解决方案
Cookie Domain配置不匹配
生产环境中,后端Session Cookie的domain设为frontend.vercel.app,但后端域名是backend.com,跨域场景下该Domain的Cookie无法被后端识别,导致无法关联到已有Session。- 修复:将生产环境Session Cookie的
domain改为backend.com,或者直接移除domain配置(让浏览器自动匹配请求域名)。
- 修复:将生产环境Session Cookie的
服务端fetch的Credentials冗余配置
服务端组件中使用fetch时,credentials: 'include'在Node.js环境下无效,且和手动传递的Cookie头可能冲突。- 修复:移除
credentials: 'include'配置,仅保留手动传递的Cookie头。
- 修复:移除
添加Partitioned属性适配跨站点Cookie
生产环境下sameSite: 'none'的跨站点Cookie,需要添加Partitioned属性才能被正确携带(需express-session版本≥1.17.3)。- 修复:在Session的cookie配置中添加
partitioned: process.env.NODE_ENV === "production"。
- 修复:在Session的cookie配置中添加
验证Cookie传递完整性
打印cookies().toString()的内容,确认是否包含connect.sid(express-session默认的Session ID Cookie名)。如果服务端组件中获取不到该Cookie,需检查Vercel部署配置,确保请求Cookie能正确传递到Next.js服务端。
内容的提问来源于stack exchange,提问作者max

