token 无感刷新

简介: token 无感刷新

什么是 token 无感刷新?为什么需要 token 无感刷新?让我们想象一下有这么个场景:你登录一个系统成功后,玩了 10 分钟,发现登录失效了,又要你重新登录,然后又过 10 分钟,又失效了,又要重新登录,难不难受,那这是怎么造成的?是因为权限 token 有效时间很短造成的,不要问,为什么权限 token 过期时间这么短,因为需要实现单点登录。那什么是单点登录呢?请参考单点登录模式

在单点登录模式下,服务器在我们登录成功后发了两个 token 给我们,一个有效时间短的权限 token(有效时间 10 分钟),一个有效时间长的刷新token(有效时间一个月)。那这个刷新 token有啥用呢,当权限token过期后,我们可以拿刷新token再去换一个新的权限token。

现在,我们需要实现的是 token 的无感刷新,那什么是 token 的无感刷新呢,就是在权限token失效后,自动拿刷新token去换新的权限 token,拿到新的权限token后继续访问系统受保护资源。不需要用户做任何操作,完全无感。

1. 接口封装

在 refreshtoken.js 中封装刷新 token 接口。

为什么需要定义 promise,因为当权限 token 失效时,但这期间同时访问了很多需要权限 token 的接口,不可能每个接口都去调用刷新接口,如果已经在调用刷新接口了,那么就赋值给 promise,在结果没返回前,再次调用刷新接口,直接就返回 promise。

为什么需要定义 __isRefreshToken 呢,因为如果刷新 token 也不存在,那么在调用刷新接口时,就会陷入死循环,需要判断当前需要权限的接口是不是刷新接口。

// refreshtoken.js
import request from "./request.js";
import { getRefreshToken } from "./token.js";
 
let promise = null;
 
export const refreshToken = () => {
  if (promise) {
    return promise;
  }
  promise = new Promise(async (resolve) => {
    const resq = await request.get("/refresh_token", {
      headers: {
        Authorization: `Bearer ${getRefreshToken()}`,
      },
      __isRefreshToken: true,
    });
    resolve(resq.code === 0);
  });
  promise.finally(() => {
    promise = null;
  });
  return promise;
};
 
export const isRefreshRequest = (config) => {
  return !!config.__isRefreshToken;
};

2. 封装 axios 请求

在 request.js 中封装 axios 请求

响应拦截中,后端返回的两个 token,我们都拿着保存着。当响应报 401 时,我们需要判断是不是调用刷新接口报的 401,如果不判断,就会一直在刷新接口这陷入死循环。刷新接口调用成功后,返回新 token,拿到新 token,赋值给 header,继续之前的请求。如果调用刷新接口失败,直接重新登录去。

// request.js
import axios from "axios";
import { setToken, setRefreshToken, getToken } from "./token.js";
import { refreshToken, isRefreshRequest } from "./refreshtoken.js";
 
const service = axios.create({
  baseURL: "http://localhost:8080",
  headers: {
    Authorization: `Bearer ${getToken()}`,
  },
});
 
// 响应拦截器
service.interceptors.response.use(async (res) => {
  if (res.headers.authorization) {
    const token = res.headers.authorization.replace("Bearer ", "");
    setToken(token);
    service.default.headers.Authorization = `Bearer ${getToken()}`;
  }
  if (res.headers.refreshtoken) {
    const refreshtoken = res.headers.refreshtoken.replace("Bearer ", "");
    setRefreshToken(refreshtoken);
  }
  if (res.data.code == 401 && !isRefreshRequest(res.config)) {
    const isSuccess = await refreshToken();
    if (isSuccess) {
      res.config.headers.Authorization = `Bearer ${getToken()}`;
      const resp = await service.request(res.config);
      return resp;
    } else {
      // 到登录页
      return res.data;
    }
  }
  return res.data;
});
 
export default service;

总结:核心代码就这些,小伙伴可以根据这些代码去继续优化到自己的项目里

目录
相关文章
|
网络协议 物联网 Unix
最新的swoole-cli已可以支持Windows,手把手带你在windows体验swoole
想必使用PHP作为开发语言的童鞋应该都听说过swoole,大致都知道swoole是什么. Swoole 使 PHP 开发人员可以编写高性能高并发的 TCP、UDP、Unix Socket、HTTP、 WebSocket 等服务,让 PHP 不再局限于 Web 领域。Swoole4 协程的成熟将 PHP 带入了前所未有的时期, 为性能的提升提供了独一无二的可能性。Swoole 可以广泛应用于互联网、移动通信、云计算、 网络游戏、物联网(IOT)、车联网、智能家居等领域。使用 PHP + Swoole 可以使企业 IT 研发团队的效率大大提升,更加专注于开发创新产品。总的来说Swoole是PHP
1729 1
|
存储 JSON 前端开发
SpringBoot 如何实现无感刷新Token
【8月更文挑战第30天】在Web开发中,Token(尤其是JWT)作为一种常见的认证方式,被广泛应用于身份验证和信息加密。然而,Token的有效期问题常常导致用户需要重新登录,从而影响用户体验。为了实现更好的用户体验,SpringBoot可以通过无感刷新Token的机制来解决这一问题。以下将详细介绍SpringBoot如何做到无感刷新Token。
808 2
|
前端开发 JavaScript Java
react中实现组件之间的转场动画
react中实现组件之间的转场动画
462 0
|
存储 算法 程序员
红黑树探险:从理论到实践,一站式掌握C++红黑树
红黑树探险:从理论到实践,一站式掌握C++红黑树
336 0
|
人工智能 Python Shell
CodeFormer——AI驱动的面部图像修复与增强
CodeFormer是由南洋理工大学和商汤科技联合研发的AI人脸复原模型,结合VQGAN和Transformer技术,能从模糊或马赛克图像中生成清晰图像。它具备老照片修复、黑白照片彩色化、马赛克修复和低码率视频增强等功能。安装过程涉及miniconda3、Python环境配置、相关库的安装及模型训练数据下载。在测试视频增强时,虽然初期遇到ffmpeg导入问题,但通过安装ffmpeg-python得以解决,不过CPU占用率高。此外,还展示了对图片进行增强的命令行操作及结果示例。
|
NoSQL Java 调度
在Spring Boot中实现分布式任务调度
在Spring Boot中实现分布式任务调度
|
JavaScript 前端开发
js阻止浏览器默认事件和防止事件传播事件
js阻止浏览器默认事件和防止事件传播事件
389 3
|
存储 Ubuntu 网络安全
百度搜索:蓝易云【Ubuntu14.04离线安装ssh所需安装包deb教程】
现在,你已经在Ubuntu 14.04离线机器上成功安装了SSH服务。注意,在离线安装过程中,可能需要手动处理依赖项问题。
493 0
|
JavaScript
vue里使用animated-scroll-to代替原生滚动实现兼容ie的平滑滚动定位
vue里使用animated-scroll-to代替原生滚动实现兼容ie的平滑滚动定位
340 0