在服务端通过Apollo Client设置Cookie
解决方案
核心思路是直接在getServerSideProps中通过服务端响应对象res设置Set-Cookie头——这是Next.js服务端渲染场景下修改响应头的标准方式,不需要依赖Apollo Client的响应流程来传递Cookie。
具体实现步骤&代码示例
- 在
getServerSideProps中获取请求Cookie里的旧JWT和刷新令牌 - 验证旧JWT是否过期,若过期则调用刷新接口获取新JWT
- 用
res.setHeader将新JWT(及更新后的刷新令牌)写入响应Cookie - 使用新JWT初始化Apollo Client,完成SSR数据请求
import { initializeApollo } from '../lib/apolloClient'; import jwt from 'jsonwebtoken'; export async function getServerSideProps(context) { const { req, res } = context; // 从请求Cookie中读取令牌 const oldAccessToken = req.cookies?.accessToken; const refreshToken = req.cookies?.refreshToken; let newAccessToken = oldAccessToken; let newRefreshToken = refreshToken; // 服务端验证JWT是否过期 const isTokenExpired = () => { if (!oldAccessToken) return true; try { const decoded = jwt.decode(oldAccessToken); return decoded.exp * 1000 < Date.now(); } catch (err) { return true; } }; // 若旧令牌过期且存在刷新令牌,请求新令牌 if (isTokenExpired() && refreshToken) { const refreshRes = await fetch(`${process.env.API_BASE_URL}/auth/refresh`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ refreshToken }), }); if (refreshRes.ok) { const { accessToken, refreshToken: updatedRefreshToken } = await refreshRes.json(); newAccessToken = accessToken; newRefreshToken = updatedRefreshToken; // 设置新令牌到响应Cookie(根据业务需求调整Cookie属性) const cookieOptions = 'HttpOnly; Secure; SameSite=Strict; Path=/'; res.setHeader('Set-Cookie', [ `accessToken=${newAccessToken}; ${cookieOptions}; MaxAge=86400`, `refreshToken=${newRefreshToken}; ${cookieOptions}; MaxAge=604800` ]); } else { // 刷新令牌也过期,重定向到登录页 return { redirect: { destination: '/login', permanent: false } }; } } // 用新令牌初始化Apollo Client const apolloClient = initializeApollo({ token: newAccessToken }); // 执行SSR数据查询 await apolloClient.query({ query: YOUR_PAGE_QUERY }); return { props: { initialApolloState: apolloClient.cache.extract(), }, }; }
关键注意事项
- Cookie安全属性:务必添加
HttpOnly(防止XSS窃取)、Secure(仅HTTPS环境下传输)、SameSite=Strict(防范CSRF),根据部署环境调整配置。 - 刷新令牌有效性校验:后端接口要验证刷新令牌的合法性(比如是否在数据库中存在、未被撤销),避免恶意使用过期/无效的刷新令牌。
- Apollo Client初始化:确保
initializeApollo函数支持动态传入token,每次getServerSideProps都能基于最新令牌创建实例。
内容的提问来源于stack exchange,提问作者omeganebula
相关产品推荐
相关产品推荐

