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

SSR模式Nuxt应用中Directus认证配置及Cookie问题排查

问题根源分析

  • 跨域限制:Nuxt(app.netlify.app/localhost)与Directus(admin.myserver.com)分属不同域名,跨域场景下Cookie的设置、携带受浏览器同源策略严格限制,当前Directus Cookie配置未适配跨域需求。
  • SSR特性:SSR时服务器端发起的请求无法直接读取客户端Cookie,页面刷新后服务器端无认证信息导致会话丢失;同时开发环境localhost为HTTP协议,Secure=true的Cookie无法被浏览器存储(Firefox对此校验更严格)。

你的问题逐个解答

  1. 是否是SSR导致的问题?
    是。SSR的服务器端/客户端请求上下文分离,跨域场景下服务器端无法获取客户端Cookie,刷新后服务器端发起的认证请求无Cookie凭证,直接导致会话失效。

  2. 配置是否正确?
    不正确:

    • Directus的Cookie域名设为admin.myserver.com,仅该域名下的请求会携带Cookie,Nuxt域名不在范围内,跨域请求无法持久化Cookie。
    • 开发环境localhost为HTTP,SESSION_COOKIE_SECURE=true会导致Cookie无法被浏览器存储。
    • SameSite=None必须搭配Secure=true,但开发环境不满足HTTPS条件,二者冲突。
  3. 是否应该使用'json'模式手动处理Cookie?
    可以作为替代方案,但需要手动管理token的存储、携带和刷新,复杂度较高,仅适合无法使用代理的场景。

  4. 是否需要在Nuxt中使用代理模块?
    是,这是最优解决方案。通过代理让Nuxt请求转发至Directus,实现同源请求,彻底规避跨域Cookie限制。

  5. 是否应该在Nuxt的/server目录下创建API?
    本质是自定义代理层,和使用代理模块效果一致,但需要手动编写转发逻辑,不如代理模块便捷高效。

最优解决方案:Nuxt代理+Directus配置调整

步骤1:安装并配置Nuxt代理模块

  1. 安装代理依赖:
npm install @nuxtjs/proxy
  1. 在nuxt.config.ts中配置代理:
export default defineNuxtConfig({
  modules: ['@nuxtjs/proxy'],
  proxy: {
    '/directus': {
      target: 'https://admin.myserver.com',
      changeOrigin: true,
      pathRewrite: { '^/directus': '' }
    }
  },
  devtools: { enabled: true }
})

步骤2:修改Directus SDK配置

将Directus请求地址改为代理路径,实现同源请求:

const directus = createDirectus('/directus')
  .with(rest({ credentials: 'include' }))
  .with(authentication('session', { credentials: 'include' }));

async function userLogin() {
  try {
    return await directus.login('username', 'password');
  } catch (error) {
    console.error(error);
  }
}

步骤3:调整Directus Cookie配置

开发环境(localhost):

REFRESH_TOKEN_COOKIE_DOMAIN=localhost
REFRESH_TOKEN_COOKIE_SECURE=false
REFRESH_TOKEN_COOKIE_SAME_SITE=lax
SESSION_COOKIE_DOMAIN=localhost
SESSION_COOKIE_SECURE=false
SESSION_COOKIE_SAME_SITE=lax
  • 关闭Secure适配HTTP环境;SameSite设为lax避免跨域限制。

生产环境:

REFRESH_TOKEN_COOKIE_SECURE=true
REFRESH_TOKEN_COOKIE_SAME_SITE=none
SESSION_COOKIE_SECURE=true
SESSION_COOKIE_SAME_SITE=none
  • 无需设置DOMAIN,代理后请求来自Nuxt域名(app.netlify.app),Directus会自动将Cookie域名设为请求来源域名,实现同源Cookie持久化。

替代方案:手动处理Token(JSON认证模式)

若无法使用代理,可采用JSON模式手动管理token:

  1. 初始化Directus SDK:
const directus = createDirectus('https://admin.myserver.com')
  .with(rest())
  .with(authentication('json'));
  1. 登录并存储token到Nuxt Cookie:
async function userLogin() {
  try {
    const { access_token, refresh_token } = await directus.login('username', 'password');
    
    // 用Nuxt的useCookie存储,确保服务器端/客户端都能访问
    const accessTokenCookie = useCookie('directus_access_token', {
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'none',
      domain: process.env.NODE_ENV === 'production' ? 'app.netlify.app' : undefined
    });
    const refreshTokenCookie = useCookie('directus_refresh_token', {
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'none',
      domain: process.env.NODE_ENV === 'production' ? 'app.netlify.app' : undefined
    });

    accessTokenCookie.value = access_token;
    refreshTokenCookie.value = refresh_token;
    return { access_token, refresh_token };
  } catch (error) {
    console.error(error);
  }
}
  1. 请求时携带token:
function getAuthenticatedDirectus() {
  const accessToken = useCookie('directus_access_token');
  return createDirectus('https://admin.myserver.com')
    .with(rest())
    .with(authentication('json', { token: accessToken.value }));
}

// 示例:获取当前用户信息
async function getCurrentUser() {
  const directus = getAuthenticatedDirectus();
  return directus.request(readMe());
}
  1. 补充token刷新逻辑:在Nuxt插件中监听token过期,用refresh_token重新获取access_token。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 07:17:06