How Vue3+Vite uses dual tokens to achieve senseless refresh
May 10, 2023 pm 01:10 PM1. Token login authentication
jwt: JSON Web Token. It is an authentication protocol that is generally used to verify the requested identity information and identity permissions. It consists of three parts: Header, Hayload, Signature
header: that is, the header information, which is the basic information describing this token. json format
{ "alg": "HS256", // 表示簽名的算法,默認(rèn)是 HMAC SHA256(寫成 HS256) "type": "JWT" // 表示Token的類型,JWT 令牌統(tǒng)一寫為JWT }
payload: payload, which is also a JSON object. Used to store the actual data that needs to be transferred. It is not recommended to store sensitive information such as passwords.
{ "iss": "a.com", // 簽發(fā)人 "exp": "1d", // expiration time 過期時(shí)間 "sub": "test", // 主題 "aud": "", // 受眾 "nbf": "", // Not Before 生效時(shí)間 "iat": "", // Issued At 簽發(fā)時(shí)間 "jti": "", // JWT ID 編號(hào) // 可以定義私有字段 "name": "", "admin": "" }
Signature is a signature of the first two parts to prevent data from being tampered with. A key needs to be specified. This key is known only to the server and cannot be leaked. Use the signature algorithm specified in the Header to generate a signature according to the formula.
After calculating the signature, combine the three parts of Header, Payload, and Signature into a string, and separate each part with . This generates a token
2. What is a double token
accessToken
: User access to datarefreshToken
: Used to obtain a new accessToken
Double token verification mechanism, where accessToken has a shorter expiration time and refreshToken has a longer expiration time. When the accessToken expires, use refreshToken to request a new token.
Double token verification process
The user logs in and sends the account password to the server. If the login fails, return to the client to log in again. After successful login, the server generates accessToken and refreshToken, and returns the generated token to the client.
In the request interceptor, the request header carries the accessToken request data, and the server verifies whether the accessToken has expired. If the token is valid, continue to request data. If the token is invalid, invalidation information will be returned to the client.
The client receives the request information sent by the server, and determines whether there is accessToken invalidation information in the twice-encapsulated axios response interceptor, but no response data is returned. If there is invalid information, bring refreshToken to request a new accessToken.
The server verifies whether the refreshToken is valid. If valid, the token will be regenerated and the new token and prompt information will be returned to the client. If invalid, invalid information will be returned to the client.
The client response interceptor determines whether the response information has a refreshToken that is valid or invalid. Invalid, log out of current login. Valid, re-store the new token and continue to request the data of the last request.
Notes
The short token is invalid. The server rejects the request and returns the token invalidation information. How can the front end request a new short token again? data to achieve the effect of non-sensitive refresh.
Server side whitelist, the token has not been requested before successful login, so if the server intercepts the request, you will not be able to log in. Customize the whitelist so that login does not require token verification.
3. Server code
1. Build koa2 server
Install koa scaffolding globally
npm install koa-generator -g
Create the server directly koa2 Project name
koa2 server
cd server Enter the project to install jwt
npm i jsonwebtoken
In order to facilitate the use of koa-cors directly on the server side cross-domain
npm i koa-cors
Introduce application cors in app.js
const cors=require('koa-cors') ... app.use(cors())
2. Double token
New utils/token.js
const jwt=require('jsonwebtoken') const secret='2023F_Ycb/wp_sd' // 密鑰 /* expiresIn:5 過期時(shí)間,時(shí)間單位是秒 也可以這么寫 expiresIn:1d 代表一天 1h 代表一小時(shí) */ // 本次是為了測(cè)試,所以設(shè)置時(shí)間 短token5秒 長token15秒 const accessTokenTime=5 const refreshTokenTime=15 // 生成accessToken const setAccessToken=(payload={})=>{ // payload 攜帶用戶信息 return jwt.sign(payload,secret,{expireIn:accessTokenTime}) } //生成refreshToken const setRefreshToken=(payload={})=>{ return jwt.sign(payload,secret,{expireIn:refreshTokenTime}) } module.exports={ secret, setAccessToken, setRefreshToken }
3. Routing
The project created directly using scaffolding is already in app.js Use routing middleware to create an interface in router/index.js
const router = require('koa-router')() const jwt = require('jsonwebtoken') const { getAccesstoken, getRefreshtoken, secret }=require('../utils/token') /*登錄接口*/ router.get('/login',()=>{ let code,msg,data=null code=2000 msg='登錄成功,獲取到token' data={ accessToken:getAccessToken(), refreshToken:getReferToken() } ctx.body={ code, msg, data } }) /*用于測(cè)試的獲取數(shù)據(jù)接口*/ router.get('/getTestData',(ctx)=>{ let code,msg,data=null code=2000 msg='獲取數(shù)據(jù)成功' ctx.body={ code, msg, data } }) /*驗(yàn)證長token是否有效,刷新短token 這里要注意,在刷新短token的時(shí)候回也返回新的長token,延續(xù)長token, 這樣活躍用戶在持續(xù)操作過程中不會(huì)被迫退出登錄。長時(shí)間無操作的非活 躍用戶長token過期重新登錄 */ router.get('/refresh',(ctx)=>{ let code,msg,data=null //獲取請(qǐng)求頭中攜帶的長token let r_tk=ctx.request.headers['pass'] //解析token 參數(shù) token 密鑰 回調(diào)函數(shù)返回信息 jwt.verify(r_tk,secret,(error)=>{ if(error){ code=4006, msg='長token無效,請(qǐng)重新登錄' } else{ code=2000, msg='長token有效,返回新的token', data={ accessToken:getAccessToken(), refreshToken:getReferToken() } } }) })
4. Application middleware
utils/auth.js
const { secret } = require('./token') const jwt = require('jsonwebtoken') /*白名單,登錄、刷新短token不受限制,也就不用token驗(yàn)證*/ const whiteList=['/login','/refresh'] const isWhiteList=(url,whiteList)=>{ return whiteList.find(item => item === url) ? true : false } /*中間件 驗(yàn)證短token是否有效 */ const cuth = async (ctx,next)=>{ let code, msg, data = null let url = ctx.path if(isWhiteList(url,whiteList)){ // 執(zhí)行下一步 return await next() } else { // 獲取請(qǐng)求頭攜帶的短token const a_tk=ctx.request.headers['authorization'] if(!a_tk){ code=4003 msg='accessToken無效,無權(quán)限' ctx.body={ code, msg, data } } else{ // 解析token await jwt.verify(a_tk,secret.(error)=>{ if(error)=>{ code=4003 msg='accessToken無效,無權(quán)限' ctx.body={ code, msg, datta } } else { // token有效 return await next() } }) } } } module.exports=auth
Introduce the application in app.js Middleware
const auth=requier(./utils/auth) ··· app.use(auth)
In fact, if you just do a simple double-token verification, many middlewares are not necessary, such as parsing static resources. However, in order to save time and convenience, I directly used koa2 scaffolding.
Final directory structure:
4. Front-end code
1. Vue3 Vite framework
The front-end uses Vue3 Vite’s framework depends on personal usage habits.
npm init vite@latest client_side
Install axios
npm i axios
2. Define the constants used
config/constants.js
export const ACCESS_TOKEN = 'a_tk' // 短token字段 export const REFRESH_TOKEN = 'r_tk' // 短token字段 export const AUTH = 'Authorization' // header頭部 攜帶短token export const PASS = 'pass' // header頭部 攜帶長token
3. Store and call expired requests
Key point: Use Promise to store requests carrying expired tokens in the array and keep them in the pending state, that is, do not call resolve(). When a new token is obtained, request again. utils/refresh.js
export {REFRESH_TOKEN,PASS} from '../config/constants.js' import { getRefreshToken, removeRefreshToken, setAccessToken, setRefreshToken} from '../config/storage' let subsequent=[] let flag=false // 設(shè)置開關(guān),保證一次只能請(qǐng)求一次短token,防止客戶多此操作,多次請(qǐng)求 /*把過期請(qǐng)求添加在數(shù)組中*/ export const addRequest = (request) => { subscribes.push(request) } /*調(diào)用過期請(qǐng)求*/ export const retryRequest = () => { console.log('重新請(qǐng)求上次中斷的數(shù)據(jù)'); subscribes.forEach(request => request()) subscribes = [] } /*短token過期,攜帶token去重新請(qǐng)求token*/ export const refreshToken=()=>{ if(!flag){ flag = true; let r_tk = getRefershToken() // 獲取長token if(r_tk){ server.get('/refresh',Object.assign({},{ headers:{[PASS]=r_tk} })).then((res)=>{ //長token失效,退出登錄 if(res.code===4006){ flag = false removeRefershToken(REFRESH_TOKEN) } else if(res.code===2000){ // 存儲(chǔ)新的token setAccessToken(res.data.accessToken) setRefreshToken(res.data.refreshToken) flag = false // 重新請(qǐng)求數(shù)據(jù) retryRequest() } }) } } }
4. Encapsulation axios
utlis/server.js
import axios from "axios"; import * as storage from "../config/storage" import * as constants from '../config/constants' import { addRequest, refreshToken } from "./refresh"; const server = axios.create({ baseURL: 'http://localhost:3004', // 你的服務(wù)器 timeout: 1000 * 10, headers: { "Content-type": "application/json" } }) /*請(qǐng)求攔截器*/ server.interceptors.request.use(config => { // 獲取短token,攜帶到請(qǐng)求頭,服務(wù)端校驗(yàn) let aToken = storage.getAccessToken(constants.ACCESS_TOKEN) config.headers[constants.AUTH] = aToken return config }) /*響應(yīng)攔截器*/ server.interceptors.response.use( async response => { // 獲取到配置和后端響應(yīng)的數(shù)據(jù) let { config, data } = response console.log('響應(yīng)提示信息:', data.msg); return new Promise((resolve, reject) => { // 短token失效 if (data.code === 4003) { // 移除失效的短token storage.removeAccessToken(constants.ACCESS_TOKEN) // 把過期請(qǐng)求存儲(chǔ)起來,用于請(qǐng)求到新的短token,再次請(qǐng)求,達(dá)到無感刷新 addRequest(() => resolve(server(config))) // 攜帶長token去請(qǐng)求新的token refreshToken() } else { // 有效返回相應(yīng)的數(shù)據(jù) resolve(data) } }) }, error => { return Promise.reject(error) } )
5. Reuse encapsulation
import * as constants from "./constants" // 存儲(chǔ)短token export const setAccessToken = (token) => localStorage.setItem(constanst.ACCESS_TOKEN, token) // 存儲(chǔ)長token export const setRefershToken = (token) => localStorage.setItem(constants.REFRESH_TOKEN, token) // 獲取短token export const getAccessToken = () => localStorage.getItem(constants.ACCESS_TOKEN) // 獲取長token export const getRefershToken = () => localStorage.getItem(constants.REFRESH_TOKEN) // 刪除短token export const removeAccessToken = () => localStorage.removeItem(constants.ACCESS_TOKEN) // 刪除長token export const removeRefershToken = () => localStorage.removeItem(constants.REFRESH_TOKEN)
6. Interface encapsulation
apis/index.js
import server from "../utils/server"; /*登錄*/ export const login = () => { return server({ url: '/login', method: 'get' }) } /*請(qǐng)求數(shù)據(jù)*/ export const getData = () => { return server({ url: '/getList', method: 'get' }) }
Project running
Finally, run the project and check the short token5 set by the backend. seconds, the length of the token is 10 seconds. After the login request reaches the token, the request data can be requested normally. If the request is made again after five seconds, the short token will become invalid. At this time, the long token will be valid. When a new token is requested, the refresh interface is only called once. After the long token expires, you need to log in again.
The above is the detailed content of How Vue3+Vite uses dual tokens to achieve senseless refresh. For more information, please follow other related articles on the PHP Chinese website!

Hot AI Tools

Undress AI Tool
Undress images for free

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Clothoff.io
AI clothes remover

Video Face Swap
Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Vue3+TS+Vite development skills: How to perform SEO optimization SEO (SearchEngineOptimization) refers to optimizing the structure, content and keywords of the website to rank it higher in search engines, thereby increasing the website's traffic and exposure. . In the development of modern front-end technologies such as Vue3+TS+Vite, how to optimize SEO is a very important issue. This article will introduce some Vue3+TS+Vite development techniques and methods to help

The problem of invalid login token can be solved by checking the network connection, checking the token validity period, clearing cache and cookies, checking login status, contacting the application developer and strengthening account security. Detailed introduction: 1. Check the network connection, reconnect to the network or change the network environment; 2. Check the token validity period, obtain a new token, or contact the developer of the application; 3. Clear cache and cookies, clear browser cache and Cookie, and then log in to the application again; 4. Check the login status.

Solutions to invalid login token include checking whether the Token has expired, checking whether the Token is correct, checking whether the Token has been tampered with, checking whether the Token matches the user, clearing the cache or cookies, checking the network connection and server status, logging in again or requesting a new Token. Contact technical support or developers, etc. Detailed introduction: 1. Check whether the Token has expired. The login Token usually has a validity period set. Once the validity period exceeds, it will be considered invalid, etc.

To achieve partial refresh of the page, we only need to implement the re-rendering of the local component (dom). In Vue, the easiest way to achieve this effect is to use the v-if directive. In Vue2, in addition to using the v-if instruction to re-render the local dom, we can also create a new blank component. When we need to refresh the local page, jump to this blank component page, and then jump back in the beforeRouteEnter guard in the blank component. original page. As shown in the figure below, how to click the refresh button in Vue3.X to reload the DOM within the red box and display the corresponding loading status. Since the guard in the component in the scriptsetup syntax in Vue3.X only has o

Vue3+TS+Vite development skills: How to carry out front-end security protection. With the continuous development of front-end technology, more and more companies and individuals are beginning to use Vue3+TS+Vite for front-end development. However, the security risks that come with it have also attracted people's attention. In this article, we will discuss some common front-end security issues and share some tips on how to protect front-end security during the development process of Vue3+TS+Vite. Input validation User input is often one of the main sources of front-end security vulnerabilities. exist

Vue3+TS+Vite development tips: How to encrypt and store data. With the rapid development of Internet technology, data security and privacy protection are becoming more and more important. In the Vue3+TS+Vite development environment, how to encrypt and store data is a problem that every developer needs to face. This article will introduce some common data encryption and storage techniques to help developers improve application security and user experience. 1. Data Encryption Front-end Data Encryption Front-end encryption is an important part of protecting data security. Commonly used

Vue3+TS+Vite development skills: How to optimize cross-domain requests and network requests Introduction: In front-end development, network requests are a very common operation. How to optimize network requests to improve page loading speed and user experience is one of the issues that our developers need to think about. At the same time, for some scenarios that require sending requests to different domain names, we need to solve cross-domain issues. This article will introduce how to make cross-domain requests and optimization techniques for network requests in the Vue3+TS+Vite development environment. 1. Cross-domain request solution

The final effect is to install the VueCropper component yarnaddvue-cropper@next. The above installation value is for Vue3. If it is Vue2 or you want to use other methods to reference, please visit its official npm address: official tutorial. It is also very simple to reference and use it in a component. You only need to introduce the corresponding component and its style file. I do not reference it globally here, but only introduce import{userInfoByRequest}from'../js/api' in my component file. import{VueCropper}from'vue-cropper&
