Nuxt Apollo首次查询认证失败问题求助
问题描述
我使用Nuxt/Apollo通过Cookie认证连接基于WPGraphQL的无头WordPress,遇到以下问题:
- 执行
npm run dev、构建项目或无痕模式首次加载页面时,查询总是失败 - 刷新页面后查询可正常运行
- 已确认首次加载的错误页面中Cookie已创建,但查询未携带该认证信息
使用版本:
- Nuxt: 3.6.5
- @NuxtJS/Apollo: 5.0.0-alpha.6
相关代码
nav-component.vue
<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设置时机不匹配,导致首个请求未携带认证头。按以下步骤修复:
- 调整认证逻辑,提前生成并注入令牌
修改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'; }); })
- 更新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', } } }, }, })
- 可选:限制查询在客户端执行(若无需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
相关产品推荐
相关产品推荐

