在 Vue.js 中捕获并重定向 JWT 令牌过期,而不会阻止 Vue 3 中的其他 401 错误

Catching and redirecting JWT token expiration in Vue.js without blocking other 401 errors in Vue 3

我无法让两件事一起工作——我的 axios 承诺捕获错误的方式中的竞争条件?详情如下:

(1) 当用户的 JWT 令牌过期时,我的 APIs return 401 和 axios 拦截路由用户注销。

main.js

createApp(App)
    .use(store)
    .use(router)
    .mount('#app')

routes.js

import axios from "axios";
import {createRouter, createWebHistory} from 'vue-router'
const routes = [
{  
    path: '/',
    name: 'Home',
    component: Home,
    meta: {requiresAuth: false}
},..]
...
const router = createRouter({
  history: createWebHistory(process.env.BASE_URL),
  routes
})

axios.interceptors.response.use(response => {
    return response;
}, error => {
    if (error.response.status === 401) {
        console.log('token expired',error.response)
        /* THIS WORKS BUT BREAKS THE LOGIN ERROR HANDLING */

    }
    return Promise.reject(error);
});

这有效,但它会中断:

(2) 如果用户 使用错误的凭据登录 ,服务器登录 API 也会 return 出现 401,我的应用程序会显示错误留言。

LogInUser.vue

methods: {
    login() {
      this.$store
        .dispatch('login', {
          username: this.username,
          password: this.password
        })
        .then(() => {
          this.$router.push({ name: 'EventList' })
        })
        .catch(err => {
          console.log(err)
          this.error = err.response.data.detail
        })
    }
  }

在我的 Vuex 商店中 store.js

login({ commit }, credentials) {
  return axios
    .post('//localhost:9000/api/login/', credentials)
    .then(({ data }) => {
      commit('SET_LOGIN_DATA', data)
    })

我可以让一个或另一个工作(正确处理登录错误,或正确处理 JWT 令牌过期错误),但不能同时使用。 axios 拦截尝试首先到达那里并尝试将用户路由到注销,然后一切都搞砸了。知道我做错了什么吗?

我解决了一个类似的问题(也许是一样的?),方法是将我的拦截器设置为一个接受 router 参数的函数,并在我的路由上使用元数据,如下所示:

Interceptor.js

export default router => {
    // In your interceptor error handler callback
    if (is401 && router.currentRoute.meta.requiresAuth === true) {
        // Redirect to logout
    }
}

main.js

import registerInterceptor from './path/to/interceptor.js'

// Initialize router and other stuff

// Register the interceptor in created() lifecycle method
new Vue({
  router,
  store,
  created () {
    registerInterceptor(this.$router)
  },
  render: h => h(App)
}).$mount('#app')

然后当我定义我的路线时,我添加一个 meta 属性 像这样:

// Some routes
{
    path: '/secure-route',
    name: 'secureRoute',
    component: ...,
    meta: {
        requiresAuth: true
    }
}

然后拦截器仅在路由需要身份验证时重定向。您可以反转它并将元命名为 属性 skipLogoutRedirect 并且在您的拦截器中只需重定向 if skipLogoutRedirect === false,这样您就不必在所有安全上定义新的 meta.requiresAuth: true路线,而只在您的登录路线上定义 meta.skipLogoutRedirect: true

如果这还不够清楚,请告诉我,我可以尝试添加更多细节。