You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在服务端通过Apollo Client设置Cookie

解决方案

核心思路是直接在getServerSideProps中通过服务端响应对象res设置Set-Cookie头——这是Next.js服务端渲染场景下修改响应头的标准方式,不需要依赖Apollo Client的响应流程来传递Cookie。

具体实现步骤&代码示例

  1. 在getServerSideProps中获取请求Cookie里的旧JWT和刷新令牌
  2. 验证旧JWT是否过期,若过期则调用刷新接口获取新JWT
  3. 用res.setHeader将新JWT(及更新后的刷新令牌)写入响应Cookie
  4. 使用新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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 14:03:26