【Token+Vue3】Token senseless refresh | token automatic refresh | token expired

Token Refresh Introduction

  1. Single token, used for login judgment
  2. Toekn expired automatic refresh
  3. Reject all front-end judgment tokens
  4. Database storage token last refresh time and refresh times
    • Up to 20 refreshes
    • If you have not logged in for 3 days, you need to log in again to refresh the token

token refresh rules

  1. The token expires and is automatically refreshed, and the number of refreshes is accumulated, the upper limit is 20 refreshes, and the token cannot be refreshed more than 20 times, and you need to log in again
  2. If the last refresh time was 3 days ago, that is, if you have not logged in for 3 days, you cannot refresh the token and you need to log in again

front-end code

Package of Axios

  • The role of packaging
    1. When initiating a token update request, if there are other requests, use promise to suspend the request first and push it to an array
    2. After the token request returns the result, re-initiate the request and execute the push array
    3. The backend status code is 456indicating that the token has expired

scr/api/axios.js

import axios from 'axios'
import {
    
     storeToRefs } from 'pinia'
import useUserInfoStore from '@/stores/userInfo' 

// 创建一个 axios 实例
const service = axios.create({
    
    
    timeout: 5000,
})

let tokenUpdateing = false,//token是否处于更新中
    reqLists = []//更新token时请求的队列 

// 请求拦截器
service.interceptors.request.use(config => {
    
    
    // 带上token发起请求
    const userInfoStore = useUserInfoStore(),
        {
    
     auth } = storeToRefs(userInfoStore)

    auth && (config.headers.auth = auth.value)

    return config

}, error => {
    
    
    // return error
    Promise.reject(error)
})

// 响应拦截器
service.interceptors.response.use(async res => {
    
    
    const {
    
     statu } = res.data,
        {
    
     url, method, params } = res.config

    // token过期
    if (statu === 456) {
    
    
        const reqConfig = {
    
     url, method, params }

        //  更新token中,先将请求配置push到reqLists,token更新完成后再重新发起请求
        if (tokenUpdateing === true) {
    
    
            //token更新中,将请求挂起
            return new Promise(resolve => {
    
    
                // token更新中,push请求 ,不push相同的请求
                const findRepeat = reqLists.findIndex(val => JSON.stringify(val) === JSON.stringify(reqConfig))

                if (findRepeat === -1) reqLists.push(reqConfig)

                resolve(service(reqConfig))
            })

            // 开始更新token
        } else {
    
    
            tokenUpdateing = true
            const uid = 6666,//用户id
                {
    
     statu, msg } = await service({
    
    //向后端请求新token 
                    url: `/api/updatetoken`,
                    params: {
    
    
                        uid,
                        sign: MD5(uid + 'usersid')//md5签名,防止篡改请求
                    }
                }),
                userInfoStore = useUserInfoStore()//重点:pinia仓库,作用:存储token

            // token请求成功
            if (statu === 200) {
    
    
               
                // 请求成功,更新token到pinia
                userInfoStore.$patch(state => {
    
    
                    state.auth = msg
                }) 
            } else {
    
    
                // token更新失败,重置pinia仓库 
                userInfoStore.$reset()
            }
	 		//token更新完成 ——> 重新发起请求
             reqLists.forEach(it => service(it)) 
             reqLists = []//清空请求队列 
             tokenUpdateing = false //关闭token更新 
				
				// 重新发起请求
               return service(reqConfig)
        }
    }

    return res.data

}, error => {
    
    
    Promise.reject(error)
})



export default service

store (pinia persistent storage)

  • pinia official website - https://pinia.web3doc.top/core-concepts/state.html#%E8%AE%BF%E9%97%AE-%E2%80%9Cstate%E2%80%9D
  • pinia-plugin-persistedstate (pinia persistent repository) - https://prazdevs.github.io/pinia-plugin-persistedstate/zh/guide/config.html

scr/store/store.js

import {
    
     defineStore } from 'pinia'

const useUserInfoStore = defineStore('userInfo', {
    
    
    state: () => {
    
    
        return {
    
    
            userName: null,
            logined: false,//是否登录
            uid: null,
            jianjie: null,
            auth: null,//登录的token 
            showLoginForm: false,//显示登录/注册表单
        }
    },
    persist: {
    
    
        key: 'userInfo',
        paths: ['auth'],

    }
})


export default useUserInfoStore

Guess you like

Origin blog.csdn.net/qq_43614372/article/details/131387406