La interfaz de VUE se da cuenta de la actualización sin sentido del token, es decir, refresco_token

Por lo general, para algunos sistemas que necesitan registrar el comportamiento del usuario, será necesario pasar el token de inicio de sesión al realizar solicitudes de red. Sin embargo, para la seguridad de los datos de la interfaz, el token del servidor generalmente no se establece durante demasiado tiempo. Por lo general, demora entre 1 y 7 días, según las necesidades. Una vez que el token caduque, deberá iniciar sesión nuevamente. Sin embargo, los inicios de sesión frecuentes provocarán una mala experiencia, por lo que si desea una buena experiencia, debe actualizar el token periódicamente y reemplazar el token anterior.

Hay tres opciones principales para lograr una actualización silenciosa de tokens:

Opcion uno:

El backend devuelve el tiempo de vencimiento y el frontend determina el tiempo de vencimiento del token cada vez que realiza una solicitud. Si se acerca el tiempo de vencimiento, se llama a la interfaz del token de actualización.

Desventajas : el backend debe proporcionar un campo adicional para el tiempo de vencimiento del token; se utiliza el criterio de hora local. Si se altera la hora local, especialmente cuando la hora local es más lenta que la hora del servidor, la interceptación fallará.

Opción II:

Escriba un temporizador y actualice la interfaz del token con regularidad.

Desventajas : desperdicio de recursos, consumo de rendimiento, no recomendado.

tercera solución:

Intercepte en el interceptor de respuesta de solicitud, determine que el token ha caducado y luego llame a la interfaz del token de actualización.

Según los tres métodos anteriores, el mejor es el tercero porque no requiere recursos adicionales. A continuación, analizamos el uso de axios para realizar solicitudes de red y luego responder a la interceptación de service.interceptors.response.

import axios from 'axios'

service.interceptors.response.use(
  response => {
    if (response.data.code === 401) {
        return refreshToken({ refreshToken: localStorage.getItem('refreshToken'), token: getToken() }).then(res => {
          const { token } = res.data
          setToken(token)
          response.headers.Authorization = `${token}`
        }).catch(err => {
          removeToken()
          router.push('/login')
          return Promise.reject(err)
        })
    }
    return response && response.data
  },
  (error) => {
    Message.error(error.response.data.msg)
    return Promise.reject(error)
  }
)

Pregunta 1: Cómo evitar múltiples actualizaciones del token

Para evitar que el token se actualice varias veces, puede usar una variable isRefreshing para controlar si el estado del token se está actualizando.

import axios from 'axios'

service.interceptors.response.use(
  response => {
    if (response.data.code === 401) {
      if (!isRefreshing) {
        isRefreshing = true
        return refreshToken({ refreshToken: localStorage.getItem('refreshToken'), token: getToken() }).then(res => {
          const { token } = res.data
          setToken(token)
          response.headers.Authorization = `${token}`
        }).catch(err => {
          removeToken()
          router.push('/login')
          return Promise.reject(err)
        }).finally(() => {
          isRefreshing = false
        })
      }
    }
    return response && response.data
  },
  (error) => {
    Message.error(error.response.data.msg)
    return Promise.reject(error)
  }
)

Pregunta 2: ¿Cómo actualizar el token cuando se inician dos o más solicitudes al mismo tiempo?

Cuando llega la segunda solicitud caducada y el token se actualiza, primero guardamos la solicitud en una cola de matriz, buscamos una manera de mantener la solicitud en espera, esperamos hasta que se actualice el token y luego volvemos a intentar borrar la cola de solicitudes una por una. uno. Entonces, ¿cómo hacer que esta solicitud quede pendiente? Para resolver este problema, tenemos que usar Promise. Después de almacenar la solicitud en la cola, se devuelve una Promesa al mismo tiempo, de modo que la Promesa siempre esté en estado Pendiente (es decir, no se llama a la resolución). En este momento, la solicitud seguirá esperando. Mientras No ejecutamos la resolución, la solicitud siempre estará ahí. Espere. Cuando regresa la interfaz de solicitud de actualización, llamamos a resolver y volvemos a intentarlo uno por uno.

import axios from 'axios'

// 是否正在刷新的标记
let isRefreshing = false
//重试队列
let requests = []
service.interceptors.response.use(
  response => {
  //约定code 409 token 过期
    if (response.data.code === 401) {
      if (!isRefreshing) {
        isRefreshing = true
        //调用刷新token的接口
        return refreshToken({ refreshToken: localStorage.getItem('refreshToken'), token: getToken() }).then(res => {
          const { token } = res.data
          // 替换token
          setToken(token)
          response.headers.Authorization = `${token}`
           // token 刷新后将数组的方法重新执行
          requests.forEach((cb) => cb(token))
          requests = [] // 重新请求完清空
          return service(response.config)
        }).catch(err => {
        //跳到登录页
          removeToken()
          router.push('/login')
          return Promise.reject(err)
        }).finally(() => {
          isRefreshing = false
        })
      } else {
        // 返回未执行 resolve 的 Promise
        return new Promise(resolve => {
          // 用函数形式将 resolve 存入,等待刷新后再执行
          requests.push(token => {
            response.headers.Authorization = `${token}`
            resolve(service(response.config))
          })
        })
      }
    }
    return response && response.data
  },
  (error) => {
    Message.error(error.response.data.msg)
    return Promise.reject(error)
  }
)

Supongo que te gusta

Origin blog.csdn.net/yu1431/article/details/130835868
Recomendado
Clasificación