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

如何在Apollo + Next.js SSR(App Router)中存储与获取认证Token

Apollo Client + Next.js 13 App Router SSR 认证方案

核心问题本质

服务端组件无法访问浏览器的localStorage,所以你之前存在localStorage的Token服务端根本拿不到。要让服务端能获取用户身份,必须把Token存在Cookie里——因为服务端可以从请求头的Cookie字段读取到当前用户的身份标识。

具体实现步骤

  1. 调整Token存储方式

    • 登录成功后,不要把Token存到localStorage,而是存到Cookie里。如果是后端返回Token,让后端直接设置Set-Cookie响应头(推荐设置HttpOnly、Secure、SameSite=Strict属性,提升安全性);如果需要前端设置,用document.cookie写入:
      document.cookie = `authToken=${token}; path=/; SameSite=Strict; Secure`;
      
  2. 服务端Apollo Client获取Token
    在Next.js 13的Server Component中,你可以通过headers()函数获取当前请求的头信息,从中解析出Cookie里的Token,然后注入到Apollo Client的请求头中。结合@apollo/experimental-nextjs-app-support/ssr的配置示例:

    // app/lib/apollo/server-client.ts
    import { createSSRApolloClient } from '@apollo/experimental-nextjs-app-support/ssr';
    import { headers } from 'next/headers';
    
    export async function getServerApolloClient() {
      const cookieHeader = headers().get('cookie');
      let authToken = '';
      if (cookieHeader) {
        const cookies = cookieHeader.split(';').reduce((acc, cookie) => {
          const [key, value] = cookie.trim().split('=');
          acc[key] = value;
          return acc;
        }, {} as Record<string, string>);
        authToken = cookies.authToken || '';
      }
    
      return createSSRApolloClient({
        uri: '你的GraphQL后端地址',
        headers: {
          Authorization: authToken ? `Bearer ${authToken}` : '',
        },
      });
    }
    

    在Server Component中直接调用这个函数创建客户端,发起的请求就会自动携带用户Token。

  3. 客户端Apollo Client同步配置
    客户端组件的Apollo Client也从Cookie中读取Token,保持前后端逻辑一致:

    // app/lib/apollo/client.ts
    import { ApolloClient, InMemoryCache, createHttpLink } from '@apollo/client';
    import { setContext } from '@apollo/client/link/context';
    
    const httpLink = createHttpLink({
      uri: '你的GraphQL后端地址',
    });
    
    const authLink = setContext((_, { headers }) => {
      // 从Cookie中读取Token
      const authToken = document.cookie.split(';').find(c => c.trim().startsWith('authToken='))?.split('=')[1] || '';
      return {
        headers: {
          ...headers,
          Authorization: authToken ? `Bearer ${authToken}` : '',
        },
      };
    });
    
    export const client = new ApolloClient({
      link: authLink.concat(httpLink),
      cache: new InMemoryCache(),
    });
    

关键注意事项

  • Cookie安全性:生产环境务必设置HttpOnly(防止XSS攻击窃取Token)和Secure(仅HTTPS传输)属性,这些需要后端来设置,前端无法设置HttpOnly。
  • SameSite属性:根据你的部署场景设置SameSite=Lax或Strict,避免跨域请求时Cookie无法携带。
  • Token过期处理:可以在Cookie中设置max-age或expires属性,自动过期;服务端请求时如果Token过期,返回401,前端跳转到登录页。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 20:01:12