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

Nuxt 2迁移Nuxt 3遇阻:认证中间件代码适配求助

Nuxt 3 适配修改方案

关键变化说明

Nuxt 3 不再提供全局 app 对象,需通过内置 Composables 获取资源,同时推荐使用 ofetch(内置轻量请求库)替代 Axios、用 Pinia 替代 Vuex 做状态管理。以下是你的认证中间件适配修改:


修改后的完整代码

1. 中间件文件(middleware/auth.js)

export default defineNuxtRouteMiddleware(async () => {
  try {
    console.log('Loading...');

    const csrfToken = await fetchCsrfToken();
    const authResult = await checkAuth("accessToken", csrfToken);

    // 调用 Pinia Store 更新状态
    const authStore = useAuthStore();
    authStore.setAuthResult(authResult?.res);

    if (authResult?.res) {
      const userInfo = await getUserInfo(csrfToken);
      authStore.setUserInfo(userInfo?.res);
      console.log(userInfo);
    }
  } catch (error) {
    console.error('Error during authentication check:', error);
  }
});

// 封装请求逻辑(用内置 $fetch 替代 Axios)
async function ajaxRequest(url, method, data) {
  const headers = {
    'Content-Type': 'application/json',
  };

  if (data) {
    data.token && (headers.Authorization = `Bearer ${data.token}`);
    data.csrfToken && (headers['X-XSRF-TOKEN'] = data.csrfToken);
  }

  try {
    return await $fetch(url, { method, headers, body: data });
  } catch (error) {
    let errorMessage;
    switch (error.statusCode) {
      case 400:
        errorMessage = `Bad Request: ${error.data}`;
        break;
      case 401:
        errorMessage = `Unauthorized: ${error.data}`;
        break;
      case 403:
        errorMessage = `Forbidden: ${error.data}`;
        break;
      default:
        errorMessage = `Request failed with status: ${error.statusCode}`;
    }
    throw new Error(errorMessage);
  }
}

// 获取 CSRF Token
async function fetchCsrfToken() {
  try {
    const response = await $fetch('/getcsrf');
    console.log('CSRF token stored in Cookies:', response.token);
    return response.token;
  } catch (error) {
    console.error('Error fetching CSRF token:', error);
    throw error;
  }
}

// 校验认证状态
async function checkAuth(tokenType, csrfToken) {
  let token;
  if (tokenType === 'accessToken') {
    token = useCookie('accessToken').value;
  } else if (tokenType === 'refreshToken') {
    token = useCookie('refreshToken').value;
  } else {
    console.error('Invalid tokenType:', tokenType);
    return;
  }

  try {
    console.log(`${tokenType} call`);
    const res = await ajaxRequest('/check-auth', 'POST', { token, csrfToken });

    if (tokenType === 'accessToken' && res === 'Refresh token required') {
      await checkAuth('refreshToken', csrfToken);
      return false;
    }

    return { res };
  } catch (error) {
    console.error('Error checking authentication:', error);
  }
}

// 获取用户信息
async function getUserInfo(csrfToken) {
  const token = useCookie('accessToken').value;
  try {
    const res = await ajaxRequest("/user-info", "POST", { token, csrfToken });
    return { res };
  } catch (error) {
    console.error('Error fetching user info:', error);
  }
}

2. Pinia 状态管理文件(stores/auth.js)

Nuxt 3 推荐用 Pinia 替代 Vuex,需先安装 @pinia/nuxt 依赖,然后创建状态文件:

export const useAuthStore = defineStore('auth', {
  state: () => ({
    authResult: null,
    userInfo: null
  }),
  actions: {
    setAuthResult(result) {
      this.authResult = result;
    },
    setUserInfo(info) {
      this.userInfo = info;
    }
  }
});

核心修改点

  1. 中间件定义:用 defineNuxtRouteMiddleware 替代原函数,不再接收 app 参数
  2. 请求库替换:用 Nuxt 内置的 $fetch 替代 app.$axios,无需额外配置
  3. Cookie 操作:用 useCookie Composable 替代 app.$cookies,自动兼容客户端/服务端
  4. 状态管理:用 Pinia 的 Store 方法替代 Vuex 的 store.commit

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 04:55:57