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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 07:06:34