React+Fastify登录授权异常:前端SessionID不一致问题求助
问题描述
我用fastify-session实现了仅登录用户可访问的Fastify路由,通过VS Code的Thunder Client测试时功能正常,登录后SessionID保持一致。但用React前端发起fetch请求时,每次请求的SessionID都不一样。
登录代码
login: async (username: string, password: string) => { try { let headersList = { Accept: "*/*", "Content-Type": "application/json", }; let bodyContent = JSON.stringify({ username: username, password: password, }); let response = await fetch("http://127.0.0.1:1338/user/login", { method: "POST", body: bodyContent, headers: headersList, credentials: 'include' }); let data = await response.json(); console.log(data); console.log("cookie: ", response.headers.getSetCookie()); if (data.user) { Cookies.set("session", JSON.stringify(data.user)); console.log("data: ", Cookies.get('session')) console.log(data); set({ user: data.user, error: null, isAuthenticated: true }); } else { console.log( "Error signing in:", data.error ); alert(data.error); set({ user: null, error: data.error, isAuthenticated: false }); } } catch (error) { console.log("Error:", error); set({ user: null, error, isAuthenticated: false }); } }
GET请求代码
const getUsers = async (page: number) => { const baseUrl = "http://127.0.0.1:1338/user"; const queryParams = new URLSearchParams(); queryParams.append("page", `${page}`); const apiUrl = `${baseUrl}?${queryParams.toString()}`; try { let response = await fetch(apiUrl, { method: "GET", headers: { "Content-Type": "application/json", }, credentials: "include", }); console.log(await response.json()); } catch (error) { console.error("Fetch error:", error); } }; export default getUsers;
我尝试调整过服务端的SameSite属性,但因服务端测试正常,认为问题不在服务端。已设置credentials: 'include',但仍无法让前端请求保持相同的SessionID,请问该如何解决?
解决方案
从现象和代码来看,问题核心是跨场景下Session Cookie的传递规则不匹配,以下是具体解决步骤:
强制服务端CORS配置允许凭证
Fastify必须明确指定前端域名并开启凭证支持,不能用*作为origin:fastify.register(require('@fastify/cors'), { origin: 'http://localhost:3000', // 替换为你的React前端实际地址 credentials: true // 关键:允许请求携带Cookie })浏览器会拒绝在origin为
*时携带Cookie,这是跨域安全规则的要求。修正服务端Session的Cookie参数
确保fastify-session的Cookie配置适配跨域场景:fastify.register(require('@fastify/session'), { secret: 'your-strong-secret-key', cookie: { path: '/', httpOnly: true, // 安全设置,禁止前端JS读取Session Cookie secure: process.env.NODE_ENV === 'production', // 生产环境必须开启(HTTPS) sameSite: process.env.NODE_ENV === 'production' ? 'none' : 'lax', maxAge: 86400000 // 会话有效期,按需调整 } })- 本地开发时用
sameSite: 'lax'即可,无需HTTPS;生产环境跨域名时,sameSite设为'none'必须搭配secure: true。 - 检查
domain参数:如果前端和服务端是子域名关系,需要设置domain: '.yourdomain.com',但本地开发(IP/localhost)不需要。
- 本地开发时用
验证浏览器Cookie的存储与携带
打开Chrome DevTools:- 进入Application > Cookies > http://127.0.0.1:1338,确认是否存在服务端设置的Session Cookie(默认名为
sessionId)。 - 发起GET请求时,查看Network > 请求头,确认
Cookie字段包含该SessionID。
如果Cookie存在但未携带,检查credentials: 'include'是否在所有请求中正确设置(你的代码已设置,可确认拼写);如果Cookie不存在,说明Set-Cookie头被浏览器拦截,检查其参数是否违反安全规则。
- 进入Application > Cookies > http://127.0.0.1:1338,确认是否存在服务端设置的Session Cookie(默认名为
移除前端手动存储的Session Cookie
代码中Cookies.set("session", ...)是前端自定义的Cookie,和服务端的Session机制无关,反而容易混淆排查。建议删除这部分代码,完全依赖服务端的Session Cookie维持登录状态。
内容的提问来源于stack exchange,提问作者MFS Craft
相关产品推荐
相关产品推荐

