Apollo Client无法将认证信息附加到请求头问题排查(NestJS、GraphQL、Apollo)
你的核心问题是跨域场景下,Apollo Client没正确从Cookie读取JWT令牌并添加到Authorization请求头,导致后端JwtAuthGuard验证失败。我整理了几个关键修复点,帮你快速解决:
1. 修正Apollo Client的credentials配置
前端跑在localhost:3000,后端在localhost:3001,属于跨域请求,但你当前设置的credentials: 'same-origin'仅在同域名下携带Cookie。需要改成include,让浏览器在跨域请求时自动传递Cookie:
export const client = new ApolloClient({ cache: new InMemoryCache(), credentials: 'include', // 将same-origin替换为include link: authLink.concat(httpLink) })
同时给httpLink也显式配置credentials(部分Apollo版本需单独设置):
const httpLink = createHttpLink({ uri: 'http://localhost:3001/graphql', credentials: 'include' // 新增这行 });
2. 延迟Cookie读取,确保每次请求拿最新令牌
你现在在初始化Client时就调用parseCookies(),只会读取一次Cookie值。如果用户刚登录后Cookie更新,后续请求仍会用旧令牌(甚至空值)。把Cookie读取逻辑放到setContext回调里,每次请求时重新获取:
const authLink = setContext((_, { headers }) => { // 每次发起请求时才读取最新的Cookie const cookies = parseCookies() const token = cookies.access_token return { headers: { ...headers, authorization: token ? `Bearer ${token}` : "", } } });
3. 确保后端GraphQL模块能接收请求头
虽然main.ts里配置了CORS,但要让NestJS的GraphQL模块把请求对象传递给Guard,需添加context配置:
GraphQLModule.forRoot({ autoSchemaFile: join(process.cwd(), 'src/schema/gql'), sortSchema: true, driver: ApolloDriver, // 新增context,把request注入GraphQL上下文 context: ({ req }) => ({ req }) })
这样JwtAuthGuard就能通过req.headers.authorization正确获取令牌了。
4. 验证GraphQL请求的实际头信息
你提供的是页面导航的请求头(Sec-Fetch-Dest: document),不是GraphQL API的请求头。打开浏览器DevTools→Network面板,筛选graphql请求,查看Request Headers里是否有Authorization: Bearer xxx:
- 如果没有,检查Cookie的
HttpOnly属性:如果后端设置了HttpOnly,前端JS无法读取Cookie,这时候要么后端把令牌返回给前端存在localStorage,要么调整Cookie属性(不推荐给前端需读取的令牌设HttpOnly); - 同时确认Cookie的
Path为/,确保整个域名下都能访问到。
按以上步骤修改后,应该就能让Apollo Client正确携带Authorization头访问受保护的GraphQL端点了。
内容的提问来源于stack exchange,提问作者kisa_2001

