在 Vue.js 中捕获和重定向 JWT 令牌过期,而不阻塞 Vue 3 中的其他 401 错误
Posted
技术标签:
【中文标题】在 Vue.js 中捕获和重定向 JWT 令牌过期,而不阻塞 Vue 3 中的其他 401 错误【英文标题】:Catching and redirecting JWT token expiration in Vue.js without blocking other 401 errors in Vue 3 【发布时间】:2021-08-29 19:04:31 【问题描述】:我无法让两件事一起工作——关于我的 axios 承诺捕获错误的方式中的竞争条件?以下是详细信息:
(1) 当用户的 JWT 令牌过期时,我的 API 返回 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 也会返回 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 拦截器尝试先到达那里并尝试将用户路由到注销,然后一切都搞砸了。任何想法我做错了什么?
【问题讨论】:
【参考方案1】:我已经解决了一个类似的问题(也许是一样的?),方法是将我的拦截器设置为一个接受 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
,并在您的拦截器中仅重定向skipLogoutRedirect === false
,因此您不必在所有安全路由上定义新的meta.requiresAuth: true
,而只需定义meta.skipLogoutRedirect: true
on您的登录路线。
如果这还不够清楚,请告诉我,我可以尝试添加更多细节。
【讨论】:
谢谢——我知道这是正确的做法,并为我的路由添加了身份验证属性,但由于某种原因,我无法在拦截处理程序中访问router.currentRoute.meta.requiresAuth
。 >TypeError:无法读取未定义的属性“requiresAuth”
你是如何初始化路由器然后设置你的拦截器的?
我刚刚更新了答案。再次查看main.js
部分,看看是否可以修复它。我刚刚意识到我最初并没有包含那个细节。
嗨!我用我的初始化方式更新了 q 。我使用的是 Vue 3 语法,这让我感到困惑,我是如何使用新的 Vue 3 初始化样式编写的。
你的拦截器需要在它自己的文件中定义。然后无论你挂载 Vue 应用程序本身,你都可以调用该拦截器函数并传递路由器实例。 或者看起来你应该可以使用router
,因为你的拦截器是在下面创建router
的地方定义的。以上是关于在 Vue.js 中捕获和重定向 JWT 令牌过期,而不阻塞 Vue 3 中的其他 401 错误的主要内容,如果未能解决你的问题,请参考以下文章
使用过期令牌发出同时 API 请求时如何避免多个令牌刷新请求