Проверка токена аутентификации, действительного перед входом маршрута в маршрутизатор Vue

у меня есть простой случай использования, где мое приложение использует vue-router и vuex. Тогда store содержит

4 ответов


Попробуйте Vue.JS Mixins

вы можете определить глобальный Mixin и использовать его через Vue.use(myMixin) - тогда все компоненты наследуют этот mixin. Если вы определяете mounted или, наверное, лучше activated крюк на mixin, он будет вызван на каждом компоненте.

там можно использовать все компонента - this укажет на ваш компонент. И если компонент также определяет сам крючок, крючок mixin того же типа будет работать до компоненты имеют крюк.

или попробуйте один компонент входа верхнего уровня

мы использовали немного другое решение - у нас есть один компонент, который обрабатывает все, что связано с логином, который существует вне представления маршрутизатора в Родительском индексе.формат html. Этот компонент всегда активен и может скрыть маршрутизатор div-view и наложить сообщение загрузки или экран входа в систему. Для интрасети-приложения этот компонент также будет использовать опрос для сохранения сеанса до тех пор, пока браузер остается открытым.

вы можете загрузить навигацию маршрутизатора к этому компоненту. - Таким образом, дочерний компонент, который хочет вызвать навигацию маршрутизатора, просто устанавливает глобальное реактивное свойство navigateTo который просматривается компонентом аутентификации верхнего уровня. Это вызовет проверку подлинности, возможно, рабочий процесс входа в систему, и после этого компонент верхнего уровня вызовет $router.push() при таком подходе у вас есть полный контроль над любой навигацией.


Я делаю что-то подобное в одном из моих проектов, на самом деле обманчиво сложно обрабатывать такие ситуации, но вы можете добавить 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";
  })
};

то на вашем маршруте вы можете сделать:

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

вы можете заметить, что я использовал location.href, а не router.push. Я делаю это, потому что моя форма входа защищена csrf, поэтому мне нужен новый csrf_token.

ваш другой вопрос быть, если пользователь пытается взаимодействовать с вашей страницей без изменения маршрута (т. е. они нажимают кнопку и получают ответ 401). Для этого мне проще всего проверить аутентификацию на каждом axios запрос и перенаправить к login когда я получаю ответ 401.

что касается добавления загрузочного счетчика во время проверки guard, вы можете просто добавить флаг загрузки в свой магазин vuex, а затем импортировать свой магазин в свой маршрутизатор. Честно говоря, хотя я бы не беспокоился, на приличном производственном сервере проверка будет выполнена так быстро, что пользователь вряд ли когда-нибудь увидеть его.


можно использовать 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);
   });

потому что вы используете vuex, вы можете добавить некоторое состояние, как isLoading или isChecking.

и в router.beforeEach, вы можете проверить и установить isLoading или isChecking следуйте текущему состоянию проверки. Затем вы можете показать сообщение загрузки, следуя этому состоянию.