web-dev-qa-db-fra.com

Vérification du jeton d'authentification valide avant l'itinéraire entrez dans Vue router

J'ai un cas d'utilisation simple, où mon application utilise vue-router et vuex. store contient alors un objet user qui est null au début. Une fois que l'utilisateur est validé depuis le serveur, il renvoie un objet user qui contient un jeton d'authentification JWT qui est affecté à l'objet user dans le magasin. Supposons maintenant que l'utilisateur soit revenu après 3 heures et ait tenté de visiter un itinéraire ou d'effectuer toute autre action, étant donné que le jeton d'authentification a expiré d'ici là, quelle serait la meilleure façon de vérifier cela (besoin d'appeler axios post pour le vérifier) ​​et redirigez l'utilisateur vers la page login. Mon application aura beaucoup de composants, donc je sais que je peux écrire une logique pour vérifier le jeton valide dans le crochet mounted de chaque composant, mais cela signifierait de le répéter tous les composants. De plus, je ne veux pas utiliser la protection de navigation beforeEach car je ne peux pas montrer de commentaires visuels à l'utilisateur comme checking... ou loading....

11
Soham Dasgupta

Essayez Vue.JS Mixins

Vous pouvez définir un mixage global et l'utiliser via Vue.use(myMixin) - alors tous les composants hériteront de ce mixage. Si vous définissez un mounted ou probablement mieux activated hook sur le mixin, il sera appelé sur chaque composant.

Là, vous pouvez utiliser tout ce qu'un composant peut faire - this pointera vers votre composant. Et si le composant définit également un hook lui-même, le hook mixin du même type s'exécutera avant le propre hook du composant.

Ou essayez un seul composant de connexion de niveau supérieur

Nous avons utilisé une solution légèrement différente - nous avons un seul composant qui gère tout ce qui concerne la connexion, qui existe en dehors de la vue du routeur dans le parent index.html. Ce composant est toujours actif et peut masquer la vue du routeur div et superposer un message de chargement ou un écran de connexion. Pour une application intranet, ce composant utilisera également l'interrogation pour maintenir la session active tant que le navigateur reste ouvert.

Vous pouvez charger votre routeur de navigation sur ce composant. - Ainsi, un composant enfant qui veut déclencher une navigation par routeur définit simplement une propriété réactive globale navigateTo qui est surveillée par le composant d'authentification de niveau supérieur. Cela déclenchera une vérification d'authentification, éventuellement un flux de travail de connexion et après cela, le composant de niveau supérieur appellera $router.Push() Avec cette approche, vous avez un contrôle complet sur toute navigation.

9
Falco

Je fais quelque chose de similaire dans l'un de mes projets, il est en fait trompeusement difficile de gérer ces types de situations, mais vous pouvez ajouter un garde beforeEnter à vos itinéraires protégés, puis rediriger si l'authentification a échoué.

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";
  })
};

Ensuite, sur votre itinéraire, vous pouvez faire:

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

Vous remarquerez peut-être que j'ai utilisé location.href plutôt que router.Push. Je le fais parce que mon formulaire de connexion est protégé par csrf, j'ai donc besoin d'un nouveau csrf_token.

Votre autre problème va se poser si l'utilisateur essaie d'interagir avec votre page sans modifier l'itinéraire (c'est-à-dire qu'il clique sur un bouton et obtient une réponse 401). Pour cela, je trouve plus facile de vérifier l'authentification sur chaque demande axios et de rediriger vers login lorsque je reçois une réponse 401.

En termes d'ajout d'un spinner de chargement pendant le contrôle de garde, vous pouvez simplement ajouter un indicateur de chargement à votre magasin vuex puis importer votre magasin dans votre routeur. Honnêtement, même si cela ne me dérangerait pas, sur un serveur de production décent, la vérification sera effectuée si rapidement qu'il est peu probable que l'utilisateur la voie.

9
craig_h

Parce que vous utilisez vuex, vous pouvez ajouter un état comme isLoading ou isChecking.

Et dans votre router.beforeEach, vous pouvez vérifier et définir isLoading ou isChecking suivre votre état de vérification actuel. Ensuite, vous pouvez afficher le message de chargement suivre cet état.

4
Anh Nguyen

Vous pouvez utiliser interceptors pour obtenir silencieusement le jeton d'authentification lorsqu'une demande se produit.

    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);
   });
4
Thaadikkaaran