在路由进入Vue路由器之前检查auth令牌是否有效

Soh*_*pta 12 vue.js vue-router vue-component vuex vuejs2

我有一个简单的用例,我的应用程序正在使用vue-routervuex.然后store包含一个开头的user对象null.在从服务器验证用户之后,它发回一个user对象,该对象包含JWT分配给user商店中对象的身份验证令牌.现在让我们假设用户在3小时后回来并尝试访问路由或执行任何其他操作,考虑到当时的身份验证令已过期,最好的方法是检查(需要调用axios post检查)并将用户重定向到该login页面.我的应用程序将有大量的组件,所以我知道我可以编写逻辑来检查mounted每个组件的钩子中有效的令牌,但这意味着重复所有组件.此外,我不想使用beforeEach导航防护,因为我无法向用户显示任何视觉反馈,如checking...loading....

cra*_*g_h 9

我在我的一个项目中做了类似的事情,实际上看起来很难处理这些类型的情况,但你可以beforeEnter为受保护的路由添加一个保护,然后在认证失败时重定向.

const guard = function(to, from, next) {
  // check for valid auth token
  axios.get('/api/checkAuthToken').then(response => {
      // Token is valid, so continue
      next();
  }).catch(error => {
      // There was an error so redirect
      window.location.href = "/login";
  })
};
Run Code Online (Sandbox Code Playgroud)

然后在您的路线上,你可以做:

{
  path: '/dashboard',
  component: Dashboard,
  beforeEnter: (to, from, next) => {
    guard(to, from, next);
  }
},
Run Code Online (Sandbox Code Playgroud)

您可能会注意到我使用过location.href而不是router.push.我这样做是因为我的登录表单是csrf保护的,所以我需要一个新的csrf_token.

如果用户尝试与您的页面进行交互而不更改路由(即他们单击按钮并获得401响应),则会出现另一个问题.为此,我发现最简单的方法是检查每个axios请求的身份验证,并login在收到401响应时重定向到.

在保护检查期间添加加载微调器时,您只需向vuex商店添加加载标志,然后将商店导入路由器.老实说虽然我不打扰,但在一个不错的生产服务器上,检查将很快完成,用户不太可能看到它.


Fal*_*lco 9

尝试Vue.JS 混入

您可以定义Global Mixin并通过它来使用Vue.use(myMixin)- 然后所有组件都将继承此mixin.如果你在mixin上定义一个mounted或者更好的activated钩子,它将在每个组件上调用.

在那里,您可以使用组件可以执行的所有操作 - this将指向您的组件.如果组件也定义了一个钩子本身,那么相同类型的mixin钩子将组件拥有钩子之前运行.

或者尝试使用单个顶级登录组件

我们使用了一个不同的解决方案 - 我们有一个组件来处理与登录相关的所有内容,它存在于父index.html中的router-view之外.此组件始终处于活动状态,可以隐藏div路由器视图并覆盖加载消息或登录屏幕.对于Intranet应用程序,只要浏览器保持打开状态,此组件也将使用轮询来保持会话处于活动状态.

您可以将路由器导航加载到此组件.- 因此,想要触发路由器导航的子组件只设置navigateTo由顶级认证组件监视的全局响应属性.这将触发身份验证检查,可能是登录工作流,之后顶级组件将调用$router.push()此方法,您可以完全控制任何导航.


Tha*_*ran 5

interceptors当某些请求发生时,您可以使用静默方式获取身份验证令牌。

    axios.interceptors.response.use(function (response) {
         return response;
       }, function (error) {

              const originalRequest = error.config;

             if (error.response.status === 401 && !originalRequest._retry) {

              originalRequest._retry = true;

              const rToken = window.localStorage.getItem('rToken');
              return axios.post('url/to/get/refresh/token', { rToken })
                     .then(({data}) => {
                     window.localStorage.setItem('token', data.token);
                     window.localStorage.setItem('rToken', data.refreshToken);
                     axios.defaults.headers.common['Authorization'] = 'Bearer ' + data.token;
                    originalRequest.headers['Authorization'] = 'Bearer ' + data.token;
                    return axios(originalRequest);
           });
      }

      return Promise.reject(error);
   });
Run Code Online (Sandbox Code Playgroud)