You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

React+Apollo Client+GraphQL:刷新Cookie无法稳定携带至请求头问题

我之前在开发跨域认证的项目时,也碰到过类似的Apollo Client随机丢失Cookie的问题,结合你给出的配置,大概率是Cookie属性或者跨域配置的细节没处理到位,给你几个排查和调整的方向:

1. 检查Refresh Token的Cookie属性(最可能的原因)

随机出现的Cookie不发送,90%以上和Cookie的SameSiteSecure属性有关。你的React是HTTPS(3000端口),NestJS是HTTP(4000端口),属于跨域场景,必须确保Cookie的属性符合浏览器的安全策略:

  • SameSite:跨域请求必须设置为SameSite=None,否则浏览器会在某些场景下(比如非GET请求、或者浏览器的默认Lax模式)随机拒绝发送Cookie。
  • Secure:本地开发时NestJS是HTTP,所以不能设置Secure(这个属性要求只有HTTPS请求才会发送Cookie),生产环境切换到HTTPS后再开启。
  • HttpOnly:这个是必须的,防止XSS攻击,但不影响Cookie的发送。

你可以修改NestJS里设置Cookie的代码,根据环境动态调整属性:

// 在你的Mutation解析器中
const isDev = process.env.STAGE === 'dev';
const refreshTokenCookie = `refreshToken=${refreshToken.value}; HttpOnly; SameSite=${isDev ? 'Lax' : 'None'}; ${isDev ? '' : 'Secure'}; Path=/; Max-Age=${refreshToken.expiresIn}`;
context.res.setHeader('Set-Cookie', refreshTokenCookie);

注意:如果本地开发时强制设置Secure,浏览器会把这个Cookie标记为“仅HTTPS可用”,不会发送到HTTP的NestJS服务,这就会导致Cookie存在但不发送的情况。

2. 统一Apollo Client的Credentials配置

你现在在ApolloClient实例和httpLink里都设置了credentials: 'include',虽然理论上不冲突,但建议统一配置,避免潜在的优先级问题。可以去掉ApolloClient实例里的credentials,只保留httpLink的配置:

this.apolloClient = new ApolloClient({
  cache: this.cache,
  link: this.authLink.concat(this.httpLink),
  connectToDevTools: process.env.REACT_APP_STAGE === 'dev',
  // 移除这里的credentials配置
})
private readonly httpLink = createHttpLink({
  uri: `${process.env.REACT_APP_API_URL}`,
  credentials: 'include', // 只在这里设置即可
})

另外,fetchOptions里的credentials也可以去掉,因为createHttpLinkcredentials参数已经会处理fetch的credentials选项了。

3. 确保NestJS的CORS配置全局生效

有时候GraphQL模块的CORS配置可能没有覆盖全局路由,导致跨域请求的响应头不符合要求。建议在main.ts里配置全局CORS,确保所有请求都能正确处理跨域凭证:

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  // 全局CORS配置
  app.enableCors({
    credentials: true,
    origin: process.env.STAGE === 'dev' ? 'https://localhost:3000' : '你的生产环境域名',
  });
  await app.listen(4000);
}
bootstrap();

这样可以避免GraphQL模块的CORS配置可能出现的遗漏,确保Access-Control-Allow-Credentials: true和正确的Access-Control-Allow-Origin头被返回。

4. 用浏览器DevTools排查实时问题

当问题出现时,打开浏览器的DevTools -> Network面板,找到对应的GraphQL请求:

  • 查看Request Headers,确认是否包含Cookie字段;
  • 查看Response Headers,确认Access-Control-Allow-CredentialstrueAccess-Control-Allow-Originhttps://localhost:3000
  • 切换到Application -> Cookies -> localhost:4000,查看Cookie的属性,如果有黄色感叹号,说明浏览器认为这个Cookie不安全,不会发送,此时需要调整Cookie的SameSiteSecure属性。

按照上面的步骤调整后,应该就能解决随机丢失Cookie的问题了。

内容的提问来源于stack exchange,提问作者mitch

火山引擎 最新活动