Cet article explique avec vous comment actualiser les jetons dans Vue. Le contenu est très bon. Les amis dans le besoin peuvent s'y référer. J'espère que cela pourra aider tout le monde.
Mécanisme d'authentification par jeton
Une fois la demande de connexion du client réussie, le serveur cryptera les informations utilisateur (telles que l'ID utilisateur) à l'aide d'un algorithme spécial et les enverra à l'utilisateur comme signe de vérification (c'est-à-dire un jeton), lorsque l'utilisateur lancera une demande la prochaine fois, ce jeton sera transféré et le serveur déchiffrera le jeton pour vérification. S'il réussit, les données demandées seront renvoyées à l'utilisateur. client ; sinon, la demande échouera.
Avantages du jeton
Il est sans état et le serveur n'a pas besoin de sauvegarder les informations de session comme l'authentification d'identité traditionnelle (session), ce qui réduit la pression sur le serveur .
Traitement de l'actualisation du jeton de Vue
Après une brève introduction au mécanisme d'authentification du jeton, saisissez le texte...
Général Pour le Pour des raisons de sécurité, le jeton définira un délai d'expiration. Après l'expiration, l'interface correspondante ne peut pas être demandée. Que dois-je faire à ce moment-là ?
Dans le projet actuel de l'entreprise, pour une meilleure expérience utilisateur, nous choisissons d'actualiser le token manuellement. Une fois la demande de connexion réussie, un jeton et le délai d'expiration du jeton seront renvoyés. Chaque fois que l'API est demandée, le frontal peut d'abord déterminer si le jeton est sur le point d'expirer ou a expiré. Si tel est le cas, demander à l'interface de s'actualiser. le jeton. Après avoir remplacé avec succès le jeton d'origine. Ce n'est qu'alors que la demande peut être réinitialisée.
Ensuite, regardons directement le code. Voici l'opération pertinente effectuée dans l'intercepteur de requêtes de vue :
/*是否有请求正在刷新token*/ window.isRefreshing = false /*被挂起的请求数组*/ let refreshSubscribers = [] /*获取刷新token请求的token*/ function getRefreshToken () { return JSON.parse(localStorage.auth).refresh_token } /*push所有请求到数组中*/ function subscribeTokenRefresh (cb) { refreshSubscribers.push(cb) } /*刷新请求(refreshSubscribers数组中的请求得到新的token之后会自执行,用新的token去请求数据)*/ function onRrefreshed (token) { refreshSubscribers.map(cb => cb(token)) } /*请求拦截器*/ ajax.interceptors.request.use( config => { const authTmp = localStorage.auth /*判断是否已登录*/ if (authTmp) { /*解析登录信息*/ let auth = JSON.parse(authTmp) /*判断auth是否存在*/ if (auth) { /*在请求头中添加token类型、token*/ config.headers.Authorization = auth.token_type + ' ' + auth.token /*判断刷新token请求的refresh_token是否过期*/ if (util.isRefreshTokenExpired()) { alert('刷新token过期,请重新登录') /*清除本地保存的auth*/ localStorage.removeItem('auth') window.location.href = '#/login' return } /*判断token是否将要过期*/ if (util.isTokenExpired() && config.url.indexOf('admin/auth/current') === -1) { /*判断是否正在刷新*/ if (!window.isRefreshing) { /*将刷新token的标志置为true*/ window.isRefreshing = true /*发起刷新token的请求*/ apiList.refreshToken({refresh_token: getRefreshToken()}).then(res => { /*将标志置为false*/ window.isRefreshing = false /*成功刷新token*/ config.headers.Authorization = res.data.data.token_type + ' ' + res.data.data.token /*更新auth*/ localStorage.setItem('auth', JSON.stringify(res.data.data)) /*执行数组里的函数,重新发起被挂起的请求*/ onRrefreshed(res.data.data.token) /*执行onRefreshed函数后清空数组中保存的请求*/ refreshSubscribers = [] }).catch(err => { alert(err.response.data.message) /*清除本地保存的auth*/ // localStorage.removeItem('auth') window.location.href = '#/login' }) } /*把请求(token)=>{....}都push到一个数组中*/ let retry = new Promise((resolve, reject) => { /*(token) => {...}这个函数就是回调函数*/ subscribeTokenRefresh((token) => { config.headers.Authorization = 'Bearer ' + token /*将请求挂起*/ resolve(config) }) }) return retry } } return config } else { /*未登录直接返回配置信息*/ return config } }, /*错误操作*/ err => { return Promise.reject(err) } )
Quelques points doivent être notés ici :
1. Lorsque le token est sur le point d'expirer ou a expiré, en principe, nous n'avons besoin que d'une interface pour déclencher une demande de rafraîchissement du token. La variable isRefreshing joue ici un tel rôle de surveillance, ce qui équivaut à. Avec un verrou, lorsque l'opération de rafraîchissement du token est déclenchée, les autres opérations de déclenchement sont exclues.
window.isRefreshing = false
2. L'interface du jeton d'actualisation utilise un autre jeton (refresh_token), qui l'est également pour des raisons de sécurité, et il a également un délai d'expiration, mais ce délai d'expiration est généralement plus long que celui des jetons ordinaires. Le délai d'expiration est plus long, donc dans le code ci-dessus, vous constaterez que lors de l'interception de la demande, je détermine d'abord si le rafraîchissement_token a expiré, je me déconnecterai directement sans passer à l'étape suivante.
/*判断刷新token请求的refresh_token是否过期*/ if (util.isRefreshTokenExpired() && config.url.indexOf('admin/auth/current') === -1) { alert('刷新token过期,请重新登录') /*清除本地保存的auth*/ localStorage.removeItem('auth') window.location.href = '#/login' return }
3. Après avoir déclenché l'opération de rafraîchissement du token, nous devons d'abord suspendre les autres requêtes, puis relancer ces requêtes après avoir obtenu le nouveau token.
/*把请求(token)=>{....}都push到一个数组中*/ let retry = new Promise((resolve, reject) => { /*(token) => {...}这个函数就是回调函数*/ subscribeTokenRefresh((token) => { config.headers.Authorization = 'Bearer ' + token /*将请求挂起*/ resolve(config) }) }) return retry
Exécutez le code suivant dans le rappel de réussite de la demande de jeton d'actualisation et relancez la demande.
/*执行数组里的函数,重新发起被挂起的请求*/ onRrefreshed(res.data.data.token)
4. Parce que quelqu'un a posé des questions sur le fichier util dans les commentaires, il veut probablement savoir comment déterminer l'expiration du jeton. En fait, lors de l'obtention du jeton, un délai d'expiration du jeton vous est renvoyé. peut d'abord le configurer, enregistrez-le d'abord, puis retirez-le et comparez-le avec l'heure locale si nécessaire
/*判断token是否过期*/ function isTokenExpired() { /*从localStorage中取出token过期时间*/ let expiredTime = new Date(JSON.parse(localStorage.auth).expired_at).getTime() / 1000 /*获取本地时间*/ let nowTime = new Date().getTime() / 1000 /*获取校验时间差*/ let diffTime = JSON.parse(sessionStorage.diffTime) /*校验本地时间*/ nowTime -= diffTime /*如果 < 10分钟,则说明即将过期*/ return (expiredTime - nowTime) < 10*60 }
Recommandations associées :
Détails de SFC et vue-loader dans Vue Analyze
Comment les valeurs sont transmises entre les composants vue parent et enfant
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!