首页 > 其他分享 >实现Token过期处理和刷新机制

实现Token过期处理和刷新机制

时间:2024-06-13 17:47:43浏览次数:17  
标签:return 过期 error Refresh Access Token export 刷新

如何处理Access Token过期并使用Refresh Token获取新的Access Token

解决方案:

  1. 在登录成功时,服务器返回给客户端两个Token:Access Token和Refresh Token。Access Token用于访问受保护的资源,而Refresh Token用于获取新的Access Token。

  2. 将Refresh Token存储在客户端(例如,浏览器的Cookie或本地存储)中,以便在Access Token过期后使用。

  3. 在每次请求受保护的资源时,客户端将Access Token附加到请求的Header中。服务器将验证Access Token的有效性,如果过期则返回401 Unauthorized错误。

  4. 当服务器返回401 Unauthorized错误时,客户端需要捕获该错误并发送一个刷新令牌的请求。

  5. 在客户端发送刷新令牌的请求时,将Refresh Token附加到请求中,并将其发送到服务器。

  6. 服务器验证Refresh Token的有效性,并生成一个新的Access Token。如果Refresh Token无效,则返回401 Unauthorized错误。

  7. 客户端接收到新的Access Token后,更新存储的Access Token,并重新发送之前失败的请求,并将新的Access Token附加到请求中。

  8. 客户端继续访问受保护的资源,并在Access Token过期前重复上述步骤。

1. request.js

首先,我们在request.js中添加拦截器来处理Token过期和刷新。

import axios from 'axios';
import { MessageBox, Message } from 'element-ui';
import store from '@/store';
import { getToken, setToken, removeToken } from '@/utils/auth';
import { refreshToken as refreshAuthToken } from '@/utils/api'; // 引入刷新token的API方法

// 创建axios实例
const service = axios.create({
  baseURL: process.env.VUE_APP_BASE_API, // api的base_url
  timeout: 5000 // 请求超时时间
});

// request拦截器
service.interceptors.request.use(
  config => {
    // 在请求发送之前做一些事情
    if (store.getters.token) {
      // 让每个请求携带token-- ['Authorization']为自定义key 请根据实际情况自行修改
      config.headers['Authorization'] = `Bearer ${getToken()}`;
    }
    return config;
  },
  error => {
    // Do something with request error
    console.log(error); // for debug
    return Promise.reject(error);
  }
);

// response拦截器
service.interceptors.response.use(
  response => {
    /**
     * code为非20000是抛错 可结合自己业务进行修改
     */
    const res = response.data;
    if (res.code !== 20000) {
      Message({
        message: res.message,
        type: 'error',
        duration: 5 * 1000
      });

      // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
      if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
        // 请自行在引入 MessageBox
        MessageBox.confirm(
          '你已被登出,可以取消继续留在该页面,或者重新登录',
          '确定登出',
          {
            confirmButtonText: '重新登录',
            cancelButtonText: '取消',
            type: 'warning'
          }
        ).then(() => {
          store.dispatch('FedLogOut').then(() => {
            location.reload(); // 为了重新实例化vue-router对象 避免bug
          });
        });
      }
      return Promise.reject('error');
    } else {
      return response.data;
    }
  },
  async error => {
    console.log('err' + error); // for debug
    const originalRequest = error.config;

    if (error.response && error.response.status === 401 && !originalRequest._retry) {
      originalRequest._retry = true;
      try {
        const tokenResponse = await refreshAuthToken();
        const newToken = tokenResponse.data.accessToken;
        setToken(newToken);
        originalRequest.headers['Authorization'] = 'Bearer ' + newToken;
        return service(originalRequest);
      } catch (refreshError) {
        store.dispatch('FedLogOut').then(() => {
          location.reload();
        });
      }
    }

    Message({
      message: error.message,
      type: 'error',
      duration: 5 * 1000
    });
    return Promise.reject(error);
  }
);

export default service;

2. api.js

在api.js中添加刷新Token的方法。

import request from '@/utils/request';

// 获取列表
export function fetchList(params) {
  return request({
    url: '/list',
    method: 'get',
    params
  });
}

// 创建列表
export function createList(data) {
  return request({
    url: '/list',
    method: 'post',
    data
  });
}

// 更新列表
export function updateList(data) {
  return request({
    url: '/list',
    method: 'put',
    data
  });
}

// 删除列表
export function removeList(data) {
  return request({
    url: '/list',
    method: 'delete',
    data
  });
}

// 刷新Token
export function refreshToken() {
  return request({
    url: '/auth/refresh-token',
    method: 'post',
    data: {
      refreshToken: getToken('refreshToken') // 获取存储的Refresh Token
    }
  });
}

3. auth.js

在utils目录下创建一个auth.js文件,用于管理Token的存储和获取。

import Cookies from 'js-cookie';

const TokenKey = 'Admin-Token';
const RefreshTokenKey = 'Admin-Refresh-Token';

// 获取Access Token
export function getToken() {
  return Cookies.get(TokenKey);
}

// 设置Access Token
export function setToken(token) {
  return Cookies.set(TokenKey, token);
}

// 移除Access Token
export function removeToken() {
  return Cookies.remove(TokenKey);
}

// 获取Refresh Token
export function getRefreshToken() {
  return Cookies.get(RefreshTokenKey);
}

// 设置Refresh Token
export function setRefreshToken(token) {
  return Cookies.set(RefreshTokenKey, token);
}

// 移除Refresh Token
export function removeRefreshToken() {
  return Cookies.remove(RefreshTokenKey);
}

4. store.js

在store.js中添加登出操作。

import { removeToken, removeRefreshToken } from '@/utils/auth';

const actions = {
  FedLogOut({ commit }) {
    return new Promise(resolve => {
      commit('SET_TOKEN', '');
      removeToken();
      removeRefreshToken();
      resolve();
    });
  }
};

export default {
  namespaced: true,
  actions
};

5. 登录逻辑

在登录成功后,需要将Access Token和Refresh Token存储起来。

import { setToken, setRefreshToken } from '@/utils/auth';

login().then(response => {
  const { accessToken, refreshToken } = response.data;
  setToken(accessToken);
  setRefreshToken(refreshToken);
});

通过以上步骤,你就可以实现Token过期自动刷新、重新请求的功能。确保在服务器端实现相应的刷新Token接口,并返回新的Access Token和Refresh Token。

标签:return,过期,error,Refresh,Access,Token,export,刷新
From: https://www.cnblogs.com/sumu80/p/18246378

相关文章

  • SentencePiece: A simple and language independent subword tokenizer and detokeniz
    郑重声明:原文参见标题,如有侵权,请联系作者,将会撤销发布! Abstract 1Introduction 2SystemOverview  3LibraryDesign 3.1LosslessTokenization  3.2Efficientsubwordtrainingandsegmentation 3.3Vocabularyidmanagement 3.4Customi......
  • Ton 区块链的官方 类ERC20-Token 智能合约代码-Transfer部分解析
    作者:林冠宏/指尖下的幽灵。转载者,请:务必标明出处。掘金:https://juejin.im/user/1785262612681997GitHub:https://github.com/af913337456/出版的书籍:《1.0-区块链DApp开发实战》《2.0-区块链DApp开发:基于公链》Ton区块链的官方类ERC20-Token智能合约代码-Trans......
  • ValueError: Tokenizer class LLaMATokenizer does not exist or is not currently im
    ValueError:TokenizerclassLLaMATokenizerdoesnotexistorisnotcurrentlyimported.解决方案:全面解析问题概述当您使用Transformers库处理与LLaMA模型相关任务时,遇到ValueError:TokenizerclassLLaMATokenizerdoesnotexistorisnotcurrentlyimported.......
  • ValueError: Tokenizer class Qwen2Tokenizer does not exist or is not currently po
    ValueError:TokenizerclassQwen2Tokenizerdoesnotexistorisnotcurrentlyported.解决方案:全面解析问题概述当您使用Qwen模型或Qwen技术相关库时,遇到ValueError:TokenizerclassQwen2Tokenizerdoesnotexistorisnotcurrentlyported.错误时,这意味着......
  • 【Redis】Redis的数据过期策略有哪些
    Redis提供了多种数据过期策略,用于管理存储在其中的数据的生命周期。数据过期策略决定了何时以及如何删除过期的数据。主要的策略有以下几种:1.定时删除(TimedDeletion)在设置键的过期时间时,Redis会创建一个定时器,当过期时间到达时自动删除该键。这种方法的优点是删除操作......
  • 记一次密码重置之token参数可逆练习及思路技巧
    杂个人漏洞实战练习记录密码重置之token参数可逆文章目录杂个人漏洞实战练习记录前言一、实验过程:1.首先访问页面,如下图所示:2.分别重置用户aaaa,admin,bbb三个用户密码,通过抓包查看数据并分析,如下图所示:3.分析:aaaa,bbb重置密码分别带有32位加密的key,初步猜测位md5加......
  • 6.9找回机制接口安全&验证码token接口
    响应包responseburp截取拦截,改相应包;思路:此处应该若是修改密码,先抓到修改成功数据包(截取验证关键字),在替换为需要绕过的数据包,截取response数据包,修改验证成功关键字达到绕过效果;1.发送验证码2.验证3.重制密码1-3跳过2;短信轰炸实例接口调用发包;应用程序注册模块没用添加......
  • 将stanfordcorenlp的tokenizer换成自定义的(或用stanfordcorenlp对自定义tokenizer分词
    本文是基于中文语料做的,对于英文语料应该也是同理,即同样适用的。分析stanfordcorenlp的分词结果,可以发现,它好像是对最小的中文词进行分词,即其对中文的分词粒度很小,这对于某些nlp场景可能就不太合适了,自然的就想到能不能将stanfordcorenlp中用于分词的tokenizer替换掉,替换成自......
  • PyQT5信号刷新时间
    importtimefromPyQt5.QtCoreimport*fromPyQt5.QtWidgetsimport*importsysclassBackendThread(QThread):update_date=pyqtSignal(str)defrun(self):whileTrue:data=QDateTime.currentDateTime()currentTim......
  • HTTP 请求中 Token 参数带引号导致后台无法识别问题
    HTTP请求中Token参数带引号导致后台无法识别问题在使用HttpClient对check_login接口进行测试时,意外地在请求头的token部分添加了引号”s4PrKYfu”,导致后台无法正确识别该参数。错误的请求如下所示:POST{{server_host}}/user/check_logintoken:"s4PrKYfu"Content-Typ......