Next.js+Apollo中getServerSideProps为何抛出Unauthorized错误?
解决ApolloClient在getServerSideProps中授权失败的问题
问题根源
你当前的ApolloClient是模块初始化时就创建的全局实例:
- 客户端执行时,
parseCookies()能自动读取浏览器Cookie,授权流程正常。 - 服务器端的
getServerSideProps中,全局实例创建时未传入当前请求的context,parseCookies()无法获取用户请求携带的Cookie,导致token为空,请求返回Unauthorized。
修复方案
1. 重构ApolloClient为创建函数
不要直接导出全局客户端,改成导出一个创建客户端的函数,接收请求context作为参数:
import { parseCookies } from 'nookies' import { setContext } from '@apollo/client/link/context'; import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client' export function createApolloClient(context) { // 服务器端传入context,即可从req中读取当前请求的Cookie const cookies = parseCookies(context) const httpLink = createHttpLink({ uri: 'http://localhost:3001/graphql', }); const authLink = setContext((_, { headers }) => { const token = cookies.access_token return { headers: { ...headers, authorization: token ? `Bearer ${token}` : "", } } }); return new ApolloClient({ cache: new InMemoryCache(), credentials: 'same-origin', link: authLink.concat(httpLink), }) }
2. 在getServerSideProps中创建请求专属客户端
修改组件的getServerSideProps,传入当前请求的context,创建对应客户端:
import { createApolloClient } from '../path/to/your-apollo-file'; // 替换为实际文件路径 import { GET_USERS } from '../path/to/your-queries'; export default function Suggestions({ users }: any) { return (<MainLayout> {JSON.stringify(users)} </MainLayout>) } export async function getServerSideProps(context: GetServerSidePropsContext) { // 传入context,创建当前请求的专属客户端 const client = createApolloClient(context); const { data } = await client.query({ query: GET_USERS }); return { props: { users: data.users }, } }
3. 客户端使用适配
在Next.js的_app.js中,同样调用这个函数创建客户端(客户端无需传入context,parseCookies()会自动读取浏览器Cookie):
import { ApolloProvider } from '@apollo/client'; import { createApolloClient } from '../path/to/your-apollo-file'; function MyApp({ Component, pageProps }) { const client = createApolloClient(); return ( <ApolloProvider client={client}> <Component {...pageProps} /> </ApolloProvider> ) } export default MyApp;
额外检查点
- 确认后端NestJS的CORS配置已经正确开启
credentials: true,且origin匹配前端地址。 - 如果使用HttpOnly Cookie,确保后端设置Cookie时
httpOnly: true(本地开发可关闭secure,生产环境建议开启)。
内容的提问来源于stack exchange,提问作者kisa_2001
相关产品推荐
相关产品推荐

