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