如何实现无感刷新(附前后端实现)?

无感刷新的核心思路:

在这里插入图片描述

无感刷新机制的目的是在用户不知情的情况下,自动更新其认证令牌(通常是Access Token),以保证用户的会话不会中断。这通常涉及到两种类型的令牌:

  1. Access Token:它是用户进行认证后得到的令牌,允许用户访问服务器的受保护资源。它有一个较短的有效期。

  2. Refresh Token:它是在同一时间发放给用户的另一个令牌,用于在Access Token过期时获取一个新的Access Token。它的有效期比Access Token长。

当Access Token即将过期或已经过期时,客户端会使用Refresh Token向认证服务器请求一个新的Access Token。如果Refresh Token仍然有效,认证服务器则发放一个新的Access Token给客户端,并且可能会同时发放一个新的Refresh Token。这个过程对用户来说是没有感知的,因此被称为“无感”刷新。

在项目中实施无感刷新:

后端实施步骤:
  1. 认证端点设置

    • 设计一个认证API端点,当用户初次登录时,返回Access Token和Refresh Token。
    • 设计一个Token刷新API端点,只接受Refresh Token并返回新的Access Token(可选地返回新的Refresh Token)。
  2. Token管理

    • Access Token应有一个短暂的生命周期,例如15分钟。
    • Refresh Token应有一个长期的生命周期,例如7天或更长,且应该存储在一个安全的存储中。
  3. 安全考虑

    • 对Refresh Token进行旋转(每次使用后就废弃旧的Refresh Token并发放一个新的)。
    • 通过HTTPS交换所有Token。
    • 应用适当的加密措施来保护Token的安全。
前端实施步骤:
  1. 存储Token

    • 在客户端安全地存储Access Token和Refresh Token(例如使用Web的localStorage或SecureStorage)。
  2. 拦截请求和响应

    • 使用拦截器监视所有出站请求和进站响应。
    • 在请求头中自动加入Access Token。
  3. 处理过期的Access Token

    • 当接收到表示Token过期的HTTP状态码(例如401)时,暂停发出的请求。
    • 使用Refresh Token请求新的Access Token。
  4. 处理新的Access Token

    • 更新存储中的Access Token。
    • 重新发送之前因Token过期而暂停的请求。
  5. 处理Refresh Token过期

    • 如果Refresh Token也过期或无效,引导用户重新登录。
无感刷新机制的大概思路就是这些,下面是具体的示例,分为简化版和完整版,简化版目的是更好的了解无感刷新的原理,而完整版就要考虑一些其他问题,比如说安全问题。

下面是实现无感刷新机制的具体示例(简化版)

这个例子涵盖前端(使用JavaScript)和后端(Node.js环境下使用Express框架)

后端(Node.js/Express)

const express = require('express');
const jwt = require('jsonwebtoken');
const app = express();
const accessTokenSecret = 'YOUR_ACCESS_TOKEN_SECRET';
const refreshTokenSecret = 'YOUR_REFRESH_TOKEN_SECRET';
let refreshTokens = [];app.post('/login', (req, res) => {// 用户登录逻辑,验证用户凭证const { username, password } = req.body;// 这里应该有逻辑来验证用户凭证// 如果验证成功:const accessToken = jwt.sign({ username }, accessTokenSecret, { expiresIn: '15m' });const refreshToken = jwt.sign({ username }, refreshTokenSecret);refreshTokens.push(refreshToken);res.json({accessToken,refreshToken});
});app.post('/refresh', (req, res) => {// 用户发送refresh token来获取新的access tokenconst { refreshToken } = req.body;if (!refreshToken || !refreshTokens.includes(refreshToken)) {return res.sendStatus(403);}jwt.verify(refreshToken, refreshTokenSecret, (err, user) => {if (err) {return res.sendStatus(403);}const newAccessToken = jwt.sign({ username: user.username }, accessTokenSecret, { expiresIn: '15m' });res.json({accessToken: newAccessToken});});
});app.listen(3000, () => {console.log('Authentication service started on port 3000');
});

前端(JavaScript/AJAX)

假设使用了axios作为HTTP客户端,可以设置拦截器来自动处理Token刷新。

axios.interceptors.response.use(response => {return response;
}, error => {const originalRequest = error.config;if (error.response.status === 401 && !originalRequest._retry) {originalRequest._retry = true;return axios.post('/refresh', {refreshToken: localStorage.getItem('refreshToken')}).then(res => {if (res.status === 200) {localStorage.setItem('accessToken', res.data.accessToken);axios.defaults.headers.common['Authorization'] = 'Bearer ' + localStorage.getItem('accessToken');return axios(originalRequest);}});}return Promise.reject(error);
});

这段代码中,我们在响应拦截器中检查任何错误的响应。如果我们得到一个401响应,并且这是第一次重试,我们就发送一个带有refreshToken的请求到/refresh端点。如果刷新Token成功,我们就保存新的accessToken,更新请求头,并重新发起失败的请求。

完整示例

实现非简化的登录无感刷新机制通常会涉及更详细的认证流程、错误处理、日志记录和安全性措施。这包括使用数据库存储Refresh Tokens、自动撤销机制、双因素认证等。

后端实现(Node.js/Express + MongoDB)

首先,你需要设置一个数据库来存储Refresh Tokens。出于安全考虑,每个Refresh Token都应该与一个用户账户关联,并且能够被追踪和撤销。

const express = require('express');
const jwt = require('jsonwebtoken');
const bcrypt = require('bcrypt');
const User = require('./models/User'); // 导入User模型
const RefreshToken = require('./models/RefreshToken'); // 导入RefreshToken模型
const app = express();// ...其他必要的中间件和数据库连接代码...app.post('/login', async (req, res) => {// 用户登录逻辑,验证用户凭证const { username, password } = req.body;const user = await User.findOne({ username });if (user && bcrypt.compareSync(password, user.password)) {const accessToken = jwt.sign({ userId: user._id }, accessTokenSecret, { expiresIn: '15m' });const refreshToken = jwt.sign({ userId: user._id }, refreshTokenSecret);// 保存refresh token到数据库const newRefreshToken = new RefreshToken({ token: refreshToken, user: user._id });await newRefreshToken.save();res.json({ accessToken, refreshToken });} else {res.status(401).send('Username or password incorrect');}
});app.post('/refresh', async (req, res) => {// 用户发送refresh token来获取新的access tokenconst { refreshToken } = req.body;const dbToken = await RefreshToken.findOne({ token: refreshToken });if (!dbToken) {return res.status(403).send('Refresh token not found');}jwt.verify(refreshToken, refreshTokenSecret, async (err, decoded) => {if (err) {return res.status(403).send('Refresh token invalid');}// 生成新的access token和refresh tokenconst newAccessToken = jwt.sign({ userId: decoded.userId }, accessTokenSecret, { expiresIn: '15m' });const newRefreshToken = jwt.sign({ userId: decoded.userId }, refreshTokenSecret);// 更新数据库中的refresh tokendbToken.token = newRefreshToken;await dbToken.save();res.json({ accessToken: newAccessToken, refreshToken: newRefreshToken });});
});app.listen(3000, () => {console.log('Authentication service started on port 3000');
});

在此示例中,我们使用了MongoDB来存储用户和他们的Refresh Tokens。登录时,我们验证用户凭证,并且如果认证成功,我们就生成Access Token和Refresh Token,然后将Refresh Token保存到数据库。在无感刷新流程中,我们验证提供的Refresh Token是否存在于数据库中,并且是否有效,然后发放新的Access Token。

前端实现(JavaScript/AJAX + Local Storage)

在前端实现中,我们需要确保存储Token的方法是安全的。在生产环境中,你可能需要考虑使用更安全的存储方式,如HTTPOnly Cookies或Secure Local Storage。

axios.interceptors.response.use(response => response,error => {const originalRequest = error.config;// 检测token过期的错误代码,比如401if (error.response.status === 401 && originalRequest.url === '/refresh') {// 刷新Token失败,直接登出用户logoutUser();return Promise.reject(error);}if (error.response.status === 401 && !originalRequest._retry) {originalRequest._retry = true;return axios.post('/refresh', { refreshToken: localStorage.getItem('refreshToken') }).then(res => {if (res.status === 200) {// 将新token设置到本地存储和axios默认头部localStorage.setItem('accessToken', res.data.accessToken);localStorage.setItem('refreshToken', res.data.refreshToken);axios.defaults.headers.common['Authorization'] = 'Bearer ' + res.data.accessToken;// 更新失败请求的头部并重新发送originalRequest.headers['Authorization'] = 'Bearer ' + res.data.accessToken;return axios(originalRequest);}}).catch(error => {// 任何错误都直接登出用户logoutUser();return Promise.reject(error);});}return Promise.reject(error);}
);function logoutUser() {// 清除本地存储和状态,重定向到登录页面localStorage.removeItem('accessToken');localStorage.removeItem('refreshToken');// ...重定向到登录页的代码...
}

在前端的实现中,我们创建了一个axios拦截器,它会在遇到401未授权的响应时自动尝试刷新Token。如果刷新Token请求也失败,则触发用户登出的逻辑。

注意:此功能一定要注意其安全性,具体的话要结合实际的项目,以下是我的一些建议:
安全方面通常包括以下几个方法:

1. 使用HTTPS来加密所有的通信。
2. 安全地存储Access Token和Refresh Token,如使用httpOnly和Secure属性的Cookies。
3. 对Token进行定期轮换,特别是Refresh Token。
4. 在服务器端验证Token的签名。
5. 设置适当的Token过期时间。
6. 实现Token撤销逻辑,以便在检测到异常时能够立即废弃使用。
7. 避免在客户端暴露敏感的认证逻辑。
8. 对所有的认证请求和Token刷新请求进行率限制和异常监测。
9. 使用跨站请求伪造(CSRF)保护措施。
10. 确保客户端和服务端都有充分的错误处理和日志记录机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/800434.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

鲁大师2024年手机Q1季报:骁龙天玑高端博弈,AI已成不可逆的大趋势

其实能够很明显的感觉到,2024年的智能手机Q1市场,恢复了近几年少有的那种激情和热闹,AI的到来,让疲于奔命在性能、影像、系统、生态之外的手机厂商们终于看到了新的发展方向。 当然,作为近几年少有的,真正能…

JAVAEE——文件IO

文章目录 文件的概念什么是文件?树型结构组织 和 目录文件路径相对路径绝对路径 文件的分类文件的权限 文件读写IO API字符流操作API 警告字节流操作APIInputStreamOutputStream 文件的概念 什么是文件? 我们先来理解一下什么是文件,那么想…

软件安全评估之设计评审入门(上)

壹 基础概念 在软件开发生命周期(Software Development Life Cycle,简称SDLC)中,设计评审(Design Review)是一个关键的阶段,旨在确保软件设计满足项目需求和目标,并且能够高效、可靠…

01 _ 分布式缘何而起:从单兵,到游击队,到集团军

这里先来聊聊什么是分布式。 与其直接用些抽象、晦涩的技术名词去给分布式下一个定义,还不如从理解分布式的发展驱动因素开始,我们一起去探寻它的本质,自然而然地也就清楚它的定义了。 这里将介绍分布式的起源,是如何从单台计算…

聚道云连接器打通红圈CRM和金蝶云星辰,赋能环境科技公司数字化转型

一、客户介绍 某环境科技有限公司是一家专注于环保科技领域的领先企业,致力于为客户提供全方位的环境解决方案。公司拥有一支经验丰富、技术精湛的团队,不断推动环保技术的创新与应用。作为业内的佼佼者,该公司在环境治理、资源回收和节能减…

深度学习理论基础(四)Parser命令行参数模块

学习目录: 深度学习理论基础(一)Python及Torch基础篇 深度学习理论基础(二)深度神经网络DNN 深度学习理论基础(三)封装数据集及手写数字识别 深度学习理论基础(四)Parse…

Datax,hbase与mysql数据相互同步

参考文章:datax mysql 和hbase的 相互导入 目录 0、软件版本说明 1、hbase数据同步至mysql 1.1、hbase数据 1.2、mysql数据 1.3、json脚本(hbase2mysql.json) 1.4、同步成功日志 2、mysql数据同步至hbase 1.1、hbase数据 1.2、mysql…

SpringBoot快速入门笔记(5)

文章目录 一、elemetnUI1、main.js2、App.vue3、fontAwesome 一、elemetnUI 开源前端框架,安装 npm i element-ui -S 建议查看官方文档 Element组件,这里是Vue2搭配elementUI,如果是vue3就搭配elementPlus,这里初学就以Vue2为例子…

docker基础学习指令

文章目录 [toc] docker基础常用指令一、docker 基础命令二、docker 镜像命令1. docker images2. docker search3. docker pull4. docker system df5. docker rmi1. Commit 命令 三、 docker 容器命令1. docker run2. docker logs3. docker top4. docker inspect5. docker cp6. …

合并主分支到子分支

参考:【Git】合并分支出现 Please enter a commit message to explain why this merge is necessary.-CSDN博客 git 如何将主分支(master)合并到子分支上_git 将主分支合并到子分支-CSDN博客 1、先切换到主分支master git checkout master 2、把主分支代码拉到本地…

RankCSE

前置知识复习 https://www.cnblogs.com/Allen-rg/p/13958508.htmlword2vec详解:https://zhuanlan.zhihu.com/p/114538417 Word2Vec和GloVe都是用于将词与向量相关联的流行词嵌入模型。 相同点: 目标:Word2Vec和GloVe的共同目标是将词汇映射…

Windows/Jerry

Jerry Enumeration nmap 扫描系统发现对外开放了 8080 端口,再次使用 nmap 扫描端口详细信息,发现运行着 Apache Tomcat ┌──(kali㉿kali)-[~/vegetable/HTB/Jerry] └─$ nmap -sV -sC -p 8080 -oA nmap 10.10.10.95 -Pn Starting Nmap 7.93 ( htt…

【QT学习】Graphics View框架(进阶篇)- 派生QGraphicsItem类创建自定义图元item

【QT学习】Graphics View框架(进阶篇)- 派生QGraphicsItem类创建自定义图元item-CSDN博客 前言 本篇,我们将通过对QGraphicsItem类进行派生,创建自定义图元item并显示在窗口中。我们将以创建一张从文件读取的图片item为例进行分…

使用Nodejs + express连接数据库mongodb

文章目录 先创建一个js文档安装 MongoDB 驱动程序:引入 MongoDB 模块:设置数据库连接:新建一个表试试执行数据库操作:关闭数据库连接: 前面需要准备的内容可看前面的文章: Express框架搭建项目 node.js 简单…

轻松上手Jackjson(珍藏版)

写在前面 虽然现在市面上有很多优秀的json解析库,但 Spring默认采用Jackson解析Json。 本文将通过一系列通俗易懂的代码示例,带你逐步掌握 Jackson 的基础用法、进阶技巧以及在实际项目中的应用场景。 一、Jackjson简介 Jackson 是当前用的比较广泛的&a…

idea开发 java web 疫情信息查询系统bootstrap框架web结构java编程计算机网页接口查询

一、源码特点 java 疫情信息查询系统是一套完善的完整信息系统,结合java web开发和bootstrap UI框架完成本系统 ,对理解JSP java编程开发语言有帮助,系统具有完整的源代码和数据库,系统主要采用B/S模式开发。 前段主要技术 css j…

The Closest Pair Problem

Problem Let S be a set of n points ((xi,yi), 1≤i≤n) in the plane, finding a pair of points p and q in S whose mutual distance is minimum. Algorithm 1: Θ ( n 2 ) The brute-force algorithm simply examines all the possible n(n−1)/2 distances and returns t…

CentOS部署Apache Superset大数据可视化BI分析工具并实现无公网IP远程访问

文章目录 前言1. 使用Docker部署Apache Superset1.1 第一步安装docker 、docker compose1.2 克隆superset代码到本地并使用docker compose启动 2. 安装cpolar内网穿透,实现公网访问3. 设置固定连接公网地址 前言 Superset是一款由中国知名科技公司开源的“现代化的…

模具行业项目管理系统哪家好?模具项目管理系统找企智汇!

模具行业是一个对项目管理要求非常高的领域,涉及到复杂的制造流程、精细的工艺要求以及紧密的供应链协作。因此,选择一款适合模具行业的项目管理系统至关重要。 企智汇作为一款专注于企业数字一体化项目管理的软件,为模具行业提供了全面的项…

解决Xshell连接不上虚拟机

相信有很多同学和我一样遇到这个问题,在网上看了很多教程基本上都先让在虚拟机输入ifconfig命令查看ip地址,弄来弄去最后还是解决不了😭😭,其实问题根本就不在命令上,很大概率是我们的虚拟机没有开启网卡&a…