最新要闻
- 俞敏洪豪横分红7.75亿,东方甄选高薪留人? 每日快看
- 【世界独家】滨海新区两个区域公用品牌登录全国名特优新农产品
- 手感温润如玉石!双曲屏新机vivo Y78+图赏-每日速递
- 深圳农民工路边即兴弹奏钢琴让人惊叹:从小热爱音乐 不甘心放弃_今日精选
- 【天天速看料】安全无选配!理想L8中保研测试结果出炉:25%碰撞A柱稳如泰山
- 近9成网友表示调休影响工作效率:摸了一天鱼 啥也没干
- 已婚女子求职被追问有几个孩子:HR称有2个孩子才算稳定
- 当前看点!公允价值变动损失同比减少 天士力一季度归母净利润同比扭亏
- 每日看点!从千兆到万兆,打造F5.5G全光万兆之城五大场景
- SMM数据 全球快看点
- 暴击RTX 4060 Ti!AMD RDNA3桌面新卡终于出鞘:RX 7600 5月见
- 新一代雪雕!技嘉Z790 AORUS ELITE AX-W主板图赏 当前观察
- 环球即时看!一文看懂Hi 畅享60与华为畅享60关键区别:国产鸿蒙系统、5G你选谁?
- “五一”国内机票订单量暴涨800%:北京飞大理近8000元
- 5月份你的工资卡里或多一笔钱:别忘了领加班费
- 华星创业:公司投资成都司元主要系业务上考虑|全球最新
手机
iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?
- 警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案
- 男子被关545天申国赔:获赔18万多 驳回精神抚慰金
- 3天内26名本土感染者,辽宁确诊人数已超安徽
- 广西柳州一男子因纠纷杀害三人后自首
- 洱海坠机4名机组人员被批准为烈士 数千干部群众悼念
家电
记录-使用双token实现无感刷新,前后端详细代码-天天头条
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助
前言
近期写的一个项目使用双token实现无感刷新。最后做了一些总结,本文详细介绍了实现流程,前后端详细代码。前端使用了Vue3+Vite,主要是axios封装,服务端使用了koa2做了一个简单的服务器模拟。
(资料图)
一、token 登录鉴权
jwt:JSON Web Token。是一种认证协议,一般用来校验请求的身份信息和身份权限。 由三部分组成:Header、Hayload、Signature
header:也就是头部信息,是描述这个 token 的基本信息,json 格式
{ "alg": "HS256", // 表示签名的算法,默认是 HMAC SHA256(写成 HS256) "type": "JWT" // 表示Token的类型,JWT 令牌统一写为JWT}payload:载荷,也是一个 JSON 对象,用来存放实际需要传递的数据。不建议存放敏感信息,比如密码。
{ "iss": "a.com", // 签发人 "exp": "1d", // expiration time 过期时间 "sub": "test", // 主题 "aud": "", // 受众 "nbf": "", // Not Before 生效时间 "iat": "", // Issued At 签发时间 "jti": "", // JWT ID 编号 // 可以定义私有字段 "name": "", "admin": ""}
Signature 签名 是对前两部分的签名,防止数据被篡改。 需要指定一个密钥。这个密钥只有服务器才知道,不能泄露。使用 Header 里面指定的签名算法,按照公式产生签名。
算出签名后,把 Header、Payload、Signature 三个部分拼成的一个字符串,每个部分之间用 . 分隔。这样就生成了一个 token
二、何为双 token
accessToken
:用户获取数据权限refreshToken
:用来获取新的accessToken
双 token 验证机制,其中 accessToken 过期时间较短,refreshToken 过期时间较长。当 accessToken 过期后,使用 refreshToken 去请求新的 token。
双 token 验证流程
- 用户登录向服务端发送账号密码,登录失败返回客户端重新登录。登录成功服务端生成 accessToken 和 refreshToken,返回生成的 token 给客户端。
- 在请求拦截器中,请求头中携带 accessToken 请求数据,服务端验证 accessToken 是否过期。token 有效继续请求数据,token 失效返回失效信息到客户端。
- 客户端收到服务端发送的请求信息,在二次封装的 axios 的响应拦截器中判断是否有 accessToken 失效的信息,没有返回响应的数据。有失效的信息,就携带 refreshToken 请求新的 accessToken。
- 服务端验证 refreshToken 是否有效。有效,重新生成 token, 返回新的 token 和提示信息到客户端,无效,返回无效信息给客户端。
- 客户端响应拦截器判断响应信息是否有 refreshToken 有效无效。无效,退出当前登录。有效,重新存储新的 token,继续请求上一次请求的数据。
注意事项
- 短token失效,服务端拒绝请求,返回token失效信息,前端请求到新的短token如何再次请求数据,达到无感刷新的效果。
- 服务端白名单,成功登录前是还没有请求到token的,那么如果服务端拦截请求,就无法登录。定制白名单,让登录无需进行token验证。
三、服务端代码
1. 搭建koa2服务器
全局安装koa脚手架
npm install koa-generator -g创建服务端 直接koa2+项目名
koa2 server
cd server 进入到项目安装jwt
npm i jsonwebtoken为了方便直接在服务端使用koa-cors 跨域
npm i koa-cors在app.js中引入应用cors
const cors=require("koa-cors")...app.use(cors())
2. 双token
新建utils/token.js
const jwt=require("jsonwebtoken")const secret="2023F_Ycb/wp_sd" // 密钥/*expiresIn:5 过期时间,时间单位是秒也可以这么写 expiresIn:1d 代表一天 1h 代表一小时*/// 本次是为了测试,所以设置时间 短token5秒 长token15秒const accessTokenTime=5 const refreshTokenTime=15 // 生成accessTokenconst setAccessToken=(payload={})=>{ // payload 携带用户信息 return jwt.sign(payload,secret,{expireIn:accessTokenTime})}//生成refreshTokenconst setRefreshToken=(payload={})=>{ return jwt.sign(payload,secret,{expireIn:refreshTokenTime})}module.exports={ secret, setAccessToken, setRefreshToken}
3. 路由
直接使用脚手架创建的项目已经在app.js使用了路由中间件 在router/index.js 创建接口
const router = require("koa-router")()const jwt = require("jsonwebtoken")const { getAccesstoken, getRefreshtoken, secret }=require("../utils/token")/*登录接口*/router.get("/login",()=>{ let code,msg,data=null code=2000 msg="登录成功,获取到token" data={ accessToken:getAccessToken(), refreshToken:getReferToken() } ctx.body={ code, msg, data }})/*用于测试的获取数据接口*/router.get("/getTestData",(ctx)=>{ let code,msg,data=null code=2000 msg="获取数据成功" ctx.body={ code, msg, data }})/*验证长token是否有效,刷新短token 这里要注意,在刷新短token的时候回也返回新的长token,延续长token, 这样活跃用户在持续操作过程中不会被迫退出登录。长时间无操作的非活 跃用户长token过期重新登录*/router.get("/refresh",(ctx)=>{ let code,msg,data=null //获取请求头中携带的长token let r_tk=ctx.request.headers["pass"] //解析token 参数 token 密钥 回调函数返回信息 jwt.verify(r_tk,secret,(error)=>{ if(error){ code=4006, msg="长token无效,请重新登录" } else{ code=2000, msg="长token有效,返回新的token", data={ accessToken:getAccessToken(), refreshToken:getReferToken() } } })})
4. 应用中间件
utils/auth.js
const { secret } = require("./token")const jwt = require("jsonwebtoken")/*白名单,登录、刷新短token不受限制,也就不用token验证*/const whiteList=["/login","/refresh"]const isWhiteList=(url,whiteList)=>{ return whiteList.find(item => item === url) ? true : false}/*中间件 验证短token是否有效*/const cuth = async (ctx,next)=>{ let code, msg, data = null let url = ctx.path if(isWhiteList(url,whiteList)){ // 执行下一步 return await next() } else { // 获取请求头携带的短token const a_tk=ctx.request.headers["authorization"] if(!a_tk){ code=4003 msg="accessToken无效,无权限" ctx.body={ code, msg, data } } else{ // 解析token await jwt.verify(a_tk,secret.(error)=>{ if(error)=>{ code=4003 msg="accessToken无效,无权限" ctx.body={ code, msg, datta } } else { // token有效 return await next() } }) } }}module.exports=auth在app.js中引入应用中间件
const auth=requier(./utils/auth)···app.use(auth)
其实如果只是做一个简单的双token验证,很多中间件是没必要的,比如解析静态资源。不过为了节省时间,方便就直接使用了koa2脚手架。
最终目录结构:
四、前端代码
1. Vue3+Vite框架
前端使用了Vue3+Vite的框架,看个人使用习惯。
npm init vite@latest client_side安装axios
npm i axios
2. 定义使用到的常量
config/constants.js
export const ACCESS_TOKEN = "a_tk" // 短token字段export const REFRESH_TOKEN = "r_tk" // 短token字段export const AUTH = "Authorization" // header头部 携带短tokenexport const PASS = "pass" // header头部 携带长token
3. 存储、调用过期请求
关键点:把携带过期token的请求,利用Promise存在数组中,保持pending状态,也就是不调用resolve()。当获取到新的token,再重新请求。 utils/refresh.js
export {REFRESH_TOKEN,PASS} from "../config/constants.js"import { getRefreshToken, removeRefreshToken, setAccessToken, setRefreshToken} from "../config/storage"let subsequent=[]let flag=false // 设置开关,保证一次只能请求一次短token,防止客户多此操作,多次请求/*把过期请求添加在数组中*/export const addRequest = (request) => { subscribes.push(request)}/*调用过期请求*/export const retryRequest = () => { console.log("重新请求上次中断的数据"); subscribes.forEach(request => request()) subscribes = []}/*短token过期,携带token去重新请求token*/export const refreshToken=()=>{ if(!flag){ flag = true; let r_tk = getRefershToken() // 获取长token if(r_tk){ server.get("/refresh",Object.assign({},{ headers:{[PASS]=r_tk} })).then((res)=>{ //长token失效,退出登录 if(res.code===4006){ flag = false removeRefershToken(REFRESH_TOKEN) } else if(res.code===2000){ // 存储新的token setAccessToken(res.data.accessToken) setRefreshToken(res.data.refreshToken) flag = false // 重新请求数据 retryRequest() } }) } }}
4. 封装axios
utlis/server.js
import axios from "axios";import * as storage from "../config/storage"import * as constants from "../config/constants"import { addRequest, refreshToken } from "./refresh";const server = axios.create({ baseURL: "http://localhost:3004", // 你的服务器 timeout: 1000 * 10, headers: { "Content-type": "application/json" }})/*请求拦截器*/server.interceptors.request.use(config => { // 获取短token,携带到请求头,服务端校验 let aToken = storage.getAccessToken(constants.ACCESS_TOKEN) config.headers[constants.AUTH] = aToken return config})/*响应拦截器*/server.interceptors.response.use( async response => { // 获取到配置和后端响应的数据 let { config, data } = response console.log("响应提示信息:", data.msg); return new Promise((resolve, reject) => { // 短token失效 if (data.code === 4003) { // 移除失效的短token storage.removeAccessToken(constants.ACCESS_TOKEN) // 把过期请求存储起来,用于请求到新的短token,再次请求,达到无感刷新 addRequest(() => resolve(server(config))) // 携带长token去请求新的token refreshToken() } else { // 有效返回相应的数据 resolve(data) } }) }, error => { return Promise.reject(error) })
5. 复用封装
import * as constants from "./constants"// 存储短tokenexport const setAccessToken = (token) => localStorage.setItem(constanst.ACCESS_TOKEN, token)// 存储长tokenexport const setRefershToken = (token) => localStorage.setItem(constants.REFRESH_TOKEN, token)// 获取短tokenexport const getAccessToken = () => localStorage.getItem(constants.ACCESS_TOKEN)// 获取长tokenexport const getRefershToken = () => localStorage.getItem(constants.REFRESH_TOKEN)// 删除短tokenexport const removeAccessToken = () => localStorage.removeItem(constants.ACCESS_TOKEN)// 删除长tokenexport const removeRefershToken = () => localStorage.removeItem(constants.REFRESH_TOKEN)
6. 接口封装
apis/index.js
import server from "../utils/server";/*登录*/export const login = () => { return server({ url: "/login", method: "get" })}/*请求数据*/export const getData = () => { return server({ url: "/getList", method: "get" })}最后的最后,运行项目,查看效果 后端设置的短token5秒,长token10秒。登录请求到token后,请求数据可以正常请求,五秒后再次请求,短token失效,这时长token有效,请求到新的token,refresh接口只调用了一次。长token也过期后,就需要重新登录啦。
本文转载于:
https://juejin.cn/post/7224764099187736634
如果对您有所帮助,欢迎您点个关注,我会定时更新技术文档,大家一起讨论学习,一起进步。
关键词:
-
易基因:ChIP-seq等揭示热休克转录因子A1b调控植物高温胁迫响应的分子机制|应激反应 环球观速讯
大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。在拟南芥中,热休克转录因子A1b(HEATSHO
来源: 一款全面又开源的区块链开发者工具箱
记录-使用双token实现无感刷新,前后端详细代码-天天头条
易基因:ChIP-seq等揭示热休克转录因子A1b调控植物高温胁迫响应的分子机制|应激反应 环球观速讯
Natasha 高级编译类 (五)- 第一部分
世界速看:开心档之C++ 类 & 对象
俞敏洪豪横分红7.75亿,东方甄选高薪留人? 每日快看
债市日报:4月24日|实时焦点
【世界独家】滨海新区两个区域公用品牌登录全国名特优新农产品
手感温润如玉石!双曲屏新机vivo Y78+图赏-每日速递
深圳农民工路边即兴弹奏钢琴让人惊叹:从小热爱音乐 不甘心放弃_今日精选
【天天速看料】安全无选配!理想L8中保研测试结果出炉:25%碰撞A柱稳如泰山
近9成网友表示调休影响工作效率:摸了一天鱼 啥也没干
已婚女子求职被追问有几个孩子:HR称有2个孩子才算稳定
MySQL(一)卸载与重装
Apple 的 plist 编辑器入门指南:基础操作与高级功能详解 快播
全球即时:编程中最难的就是命名?这几招教你快速上手
世界热点评!使用Plist编辑器——简单入门指南
Django简介 安装下载 app概念 主要目录介绍_当前时讯
当前看点!公允价值变动损失同比减少 天士力一季度归母净利润同比扭亏
全球焦点!【金融街发布】人民银行:截至2023年3月末全国共有小额贷款公司5801家 贷款余额8722亿元
每日看点!从千兆到万兆,打造F5.5G全光万兆之城五大场景
SMM数据 全球快看点
暴击RTX 4060 Ti!AMD RDNA3桌面新卡终于出鞘:RX 7600 5月见
新一代雪雕!技嘉Z790 AORUS ELITE AX-W主板图赏 当前观察
环球即时看!一文看懂Hi 畅享60与华为畅享60关键区别:国产鸿蒙系统、5G你选谁?
“五一”国内机票订单量暴涨800%:北京飞大理近8000元
5月份你的工资卡里或多一笔钱:别忘了领加班费
今日热议:【介绍】C++五种迭代器
【天天播资讯】命令执行中cat 和tac的区别
Redis Plus 来了,性能炸裂! 当前短讯
产品研发流程规范-参考|每日热文
FBEC大会 | 瑞云科技 CTO 赵志杰:元宇宙时代的基础设施——实时云渲染|天天百事通
华星创业:公司投资成都司元主要系业务上考虑|全球最新
迪士尼《小美人鱼》最新剧照:爱丽儿与六位人鱼姐姐集体亮相 天天新资讯
天天热头条丨疯狂对标比亚迪宋 吉利银河L7首车下线:CLTC能跑1300多公里
天天日报丨青春回归!腾讯音游《节奏大师》终测开启:安卓不限参与名额
苹果、高通靠边站!5G标准必要专利全球排名:华为第一 国产厂商无敌 环球通讯
环球快看:消息称特斯拉准备从上海向加拿大出口Model Y:系首次出口北美
火山的女儿神射手结局怎么达成
河北省取暖费发放标准2018_2019_河北省取暖费发放标准2018_全球资讯
精彩看点:「教程」天气预警 API 详解:申请密钥到接入代码一气呵成!
热消息:【译】如何在 Visual Studio 中调试异步代码
chatgpt~插件介绍
为什么你永远不应该在CSS中使用px来设置字体大小-今日关注
Natasha 编译单元(四)_世界快资讯
【快播报】安全头盔是个宝 骑乘人都要佩戴好
知名男演员李光洁跟电诈团伙打36分钟电话:半天才发现破绽
当前时讯:减重近一吨 我国首辆镁合金轻量化挂车交付
手机/PC双端互通!米哈游《崩坏:星穹铁道》预下载开启:4月26日上线
实拍“星舰”发射失败后现场:发射台报废、地面影像设备尽毁|世界焦点
最强拍照折叠屏!小米MIX Fold 3规格曝光:用上一英寸IMX989
打哈欠真的会传染吗 环球快看点
科创板首批“重大违法退”锁定,注册制下退市生态加速构建 世界独家
Anki 无需网络如何同步 手机和电脑进行同步
盘点| 有哪些比较新的好用的React Native 开发工具? 天天最新
快看点丨技术干货|如何利用 ChunJun 实现数据实时同步?
当前快看:python工具模块介绍-time 时间访问和转换
厦门钨业于云南新设科技发展子公司:企查查APP显示,近日,云南厦钨科技发展有限公司成立,注册资本100万元,经营范围包含 全球热文
全球热头条丨电池原材料价格大跌坑到宁王?宁德时代回应
天天快讯:每小时1000公里 !我国“高速飞车”研制取得新进展
每日热讯!马斯克请回来的4D成像雷达 百度小米蔚来也押注了:战况很激烈
《天宫之镜》上线:首次慢直播中国空间站-天天实时
每日焦点!同飞股份4月24日盘中涨幅达5%
焦点报道:C#用dynamic一行代码实现反射操作
最后时刻单防福克斯!追梦:如果这让你感觉不好 我很抱歉
北京国际电影节有哪些看点?
最新:美国迪士尼乐园13米巨龙起火 观众还以为是新节目
全球速看:酷派COOL30 Pro来了:LCD水滴屏+2.4GHz八核CPU
特斯拉市值一周蒸发逾5000亿 分析师补刀:还能跌85%
一加Ace 2原神定制礼盒太火爆!3699元首销售罄
新资讯:全球连线|菲律宾榴莲加速进军中国
SpringSecurity框架教程-简介与SpringSecurity框架教程-入门案例准备工作_每日简讯
每日视讯:顶象推出应用隐私合规检测服务
如何用 DataTester 设计并创建可视化实验-全球微速讯
焦点观察:国泰4月24日起送2.7万张免费机票,附参加方法
天天热文:漯河郾城区新店镇:打好“三张牌” 聚力招商引资新突破
今日热闻!14款新车哪个最拉胯?中保研新一轮测试成绩公布:结果惊人
简讯:公司招聘运营称已婚双休未婚单休 求职者称歧视:网友热议没啥问题
宏碁发布史上最强迷你机圣盾X:i9-13900KS、RTX 4090无可挑剔|世界看热讯
微星推新BIOS限制7000X3D系列CPU电压 避免CPU毁损风险|天天视讯
世界快看点丨汽车级磷酸铁锂 针刺不起火!绿联、比亚迪户外电源3699元新低
新恒结衣的垣怎么念?新垣结衣个人介绍
中国第二大城市是哪个?中国第二大城市介绍
批准为荷是什么意思?批准为荷和批准为盼哪个更好?
孔雀蓝是什么颜色?孔雀蓝的rgb色值是多少?
任务管理器中的进程是什么意思?任务管理器中的进程怎么关闭?
MP3音乐文件破损是什么原因?MP3音乐文件破损怎么修复?
高血压的症状表现有哪些?高血压怎么调理才能彻底根除?
痛风一般有哪些症状?痛风会导致哪些严重后果?
可以用鼠标在电脑上写字的软件有哪些?怎么用鼠标拖动改变工作表标签的先后位置?
千与千寻迅雷下载 720p_千与千寻迅雷下载链接|环球快讯
Linux下Nginx安装证书_世界热门
2023最新kali安装教程 头条
分享一波免费可用的 API 大全|每日视点
笔记本怎么下载软件到桌面?笔记本怎么下载播放器?
环球今亮点!吃烧烤不应成为一场“战斗” 淄博在激流中需要保持清醒
世界球精选!一季度全国城镇新增就业297万人
环球滚动:景区完成特种设备隐患排查
全球热资讯!努比亚Z50把骁龙8 Gen2干到2500以内!倪飞:这才是旗舰焊门员
30寸巨屏+怀挡!别克全新君越内饰亮相:整车改头换面|报道