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

Nuxt Apollo首次查询认证失败问题求助

问题描述

我使用Nuxt/Apollo通过Cookie认证连接基于WPGraphQL的无头WordPress,遇到以下问题:

  • 执行npm run dev、构建项目或无痕模式首次加载页面时,查询总是失败
  • 刷新页面后查询可正常运行
  • 已确认首次加载的错误页面中Cookie已创建,但查询未携带该认证信息

使用版本:

  • Nuxt: 3.6.5
  • @NuxtJS/Apollo: 5.0.0-alpha.6

相关代码

<script setup>
const query = gql`
  query NavigationMenu($id: ID!, $size: MediaItemSizeEnum = MEDIUM, $include: [MediaItemSizeEnum] = MEDIUM) {
    menu(id: $id, idType: DATABASE_ID) {
      count
      menuItems(first: 15) {
        nodes {
          order
          label
          uri
          connectedNode {
            node {
              databaseId
              isTermNode
              ... on Category {
                name
                posts(first: 5) {
                  nodes {
                    uri
                    title
                  }
                }
              }
            }
          }
        }
      }
    }
  }
`;

const variables = { id: 727 }

const { data: { value: { menu } } } = await useLazyAsyncQuery({
  query,
  variables,
  key: 'main-navigation',
  cache: true,
})

const menuItems = menu.menuItems.nodes;

</script>

<template>
  <nav aria-label="primary">
    <ul class="nav-primary">
      <NavItem
        v-for="{uri, label, connectedNode: { node}} in menuItems"
        :link="uri"
        :label="label"
        :key="label"
        :data="node"
      />
    </ul>
  </nav>
</template>

nuxt.config.ts

export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      apiUser: process.env.NUXT_PUBLIC_API_USER || '',
      apiPass: process.env.NUXT_PUBLIC_API_PASS || '',
    }
  },
  modules: [
    '@nuxtjs/apollo',
  ],
  apollo: {
    authType: 'Basic',
    clients: {
      default: {
        httpEndpoint: 'https://example.com/graphql',
        tokenName:'lpder',
      }
    },
  },
})

plugins/apollo.ts

export default defineNuxtPlugin((nuxtApp) => {

  const config = useRuntimeConfig();

  const cookie = useCookie('lpder')
  nuxtApp.hook('apollo:auth', ({ client, token }) => {
    const tokenized =  btoa(`${config.public.apiUser}:${config.public.apiPass}`) ;

    cookie.value = tokenized;
  })
})

解决方案

问题核心是首次请求时Apollo客户端未及时获取Cookie中的认证信息,apollo:auth钩子执行时机与Cookie设置时机不匹配,导致首个请求未携带认证头。按以下步骤修复:

  1. 调整认证逻辑,提前生成并注入令牌
    修改plugins/apollo.ts,预先生成Basic认证令牌并同步设置到Cookie与Apollo客户端:
export default defineNuxtPlugin((nuxtApp) => {
  const config = useRuntimeConfig();
  const cookie = useCookie('lpder');

  // 预生成Basic认证令牌
  const tokenized = btoa(`${config.public.apiUser}:${config.public.apiPass}`);
  // 若Cookie不存在则初始化
  if (!cookie.value) {
    cookie.value = tokenized;
  }

  // 拦截Apollo认证钩子,直接注入令牌
  nuxtApp.hook('apollo:auth', ({ auth }) => {
    auth.token = cookie.value;
    auth.type = 'Basic';
  });
})
  1. 更新Apollo配置,确保请求携带凭证
    修改nuxt.config.ts,开启请求凭证携带,保证Cookie随请求发送:
export default defineNuxtConfig({
  runtimeConfig: {
    public: {
      apiUser: process.env.NUXT_PUBLIC_API_USER || '',
      apiPass: process.env.NUXT_PUBLIC_API_PASS || '',
    }
  },
  modules: [
    '@nuxtjs/apollo',
  ],
  apollo: {
    clients: {
      default: {
        httpEndpoint: 'https://example.com/graphql',
        tokenName: 'lpder',
        // 开启凭证携带
        httpLinkOptions: {
          credentials: 'include',
        }
      }
    },
  },
})
  1. 可选:限制查询在客户端执行(若无需SSR)
    如果菜单无需服务端渲染,在组件外层包裹<ClientOnly>,避免服务端渲染时因Cookie缺失导致查询失败:
<template>
  <ClientOnly>
    <nav aria-label="primary">
      <ul class="nav-primary">
        <NavItem
          v-for="{uri, label, connectedNode: { node}} in menuItems"
          :link="uri"
          :label="label"
          :key="label"
          :data="node"
        />
      </ul>
    </nav>
  </ClientOnly>
</template>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 04:15:28