前后端分离中的无痛刷新token机制
今天我们来说一说前后端分离中的无痛刷新token机制
博主先来分享一波福利,最近挖到的宝藏,刚开始学Java的同学看
https://www.bilibili.com/video/BV1Rx411876f
学完JavaSE的同学,这个项目是对之前掌握的知识做一些运用
https://www.bilibili.com/video/BV1tV411J77q
在手机app中应该经常用到,大家都知道在前后端是以token的形式交互,既然是token,那么肯定有它的过期时间,没有一个token是永久的,永久的token就相当于一串永久的密码,是不安全的,
那么既然有刷新时间,问题就来了
- 前后端交互的过程中token如何存储?
- token过期时,前端该怎么处理
- 当用户正在操作时,遇到token过期该怎么办?直接跳回登陆页面?(你确定这样用户不会打死你吗,老子好不容易表单填完准备提交????)
token如何存储
cookie的大小约4k,兼容性在ie6及以上 都兼容,在浏览器和服务器间来回传递,因此它得在服务器的环境下运行,而且可以设定过期时间,默认的过期时间是session会话结束。
localStorage的大小约5M,兼容性在ie7及以上都兼容,有浏览器就可以,不需要在服务器的环境下运行, 会一直存在,除非手动清除 。
对于这个问题,答案大致分为2种
- 存在
cookie中 - 存在
localStorage中
我觉得都可以,两种我都用
token过期时,前端该怎么处理
思路:token过期处理方式大概就是:
- 第一种:跳回登陆页面重新登陆
- 第二种:
catch401 ,然后重新获取token
对于第一种,很简单在vue中我们可以在 axios 拦截器中这样写:
instance.interceptors.response.use(
function (response) {
// 对响应数据做点什么
return response.data
},
function (error) {
console.log(error)
if (error.response) {
if (error.response.status === 401) {
Message.error('登陆过期请重新登陆!')
setToken('')
router.push({
name: 'login'
})
}
}
}
// 对响应错误做点什么
return Promise.reject(error.response)
}
)
对于第二种,如何重新获取 token,这就要涉及到后端的知识了
来先让我讲一段废话
现代认证和/或授权解决方案已将 令牌的概念引入其协议中。令牌是经过特殊处理的数据,它们可以提供足够的信息来 授权用户执行操作,或者允许客户端 获取有关授权过程的 其他信息(然后完成它)。换句话说,令牌是允许执行授权过程的信息。客户端(或授权服务器以外的任何一方)是否可读取或解析此信息是由实现定义的。重要的是:客户端获取此信息,然后使用它来 访问资源。JSON Web令牌(JWT) 规范 定义了一种可以由实现表示公共令牌信息的方式。
JWT定义了一种方式,其中可以表示与认证/授权过程有关的某些公共信息。顾名思义,数据格式是JSON。JWT具有某些常见字段,例如主题,发行者,到期时间等。当与其他规范(如JSON Web签名(JWS)和JSON Web加密(JWE))结合使用时,JWT变得非常有用。这些规范不仅提供了授权令牌通常所需的所有信息,而且还提供了验证令牌内容的方法,使其不会被篡改(JWS)和加密信息以使其保持不透明的方式给客户(JWE)。数据格式的简单性(及其它优点)帮助JWT成为最常见的令牌类型之一。如果您有兴趣学习如何在Web应用程序中实现JWT,请查看Ryan Chenkie的这篇优秀文章。
出于本文的目的,我们将关注两种最常见的令牌类型:访问令牌和刷新令牌。
- 访问令牌携带必要的信息以直接访问资源。换句话说,当客户端将访问令牌传递给管理资源的服务器时,该服务器可以使用令牌中包含的信息来决定客户端是否被授权。访问令牌通常具有到期日期并且是短暂的。
- 刷新令牌包含获取新访问令牌所需的信息。换句话说,每当访问令牌需要访问特定资源时,客户端可以使用刷新令牌来获得由认证服务器发布的新访问令牌。常见用例包括在旧的访问令牌过期后获取新访问令牌,或者首次访问新资源。刷新令牌也可以过期,但相当长寿。刷新令牌通常受到严格的存储要求,以确保它们不会泄露。它们也可以被授权服务器列入黑名单。
标记是否不透明通常由实现定义。通用实现允许针对访问令牌进行直接授权检查。也就是说,当访问令牌被传递到管理资源的服务器时,服务器可以读取令牌中包含的信息并自己决定用户是否被授权(不需要对授权服务器进行检查)。这是必须签署令牌的原因之一(例如,使用JWS)。另一方面,刷新令牌通常需要检查授权服务器。这种处理授权检查的分割方式允许三件事:
- 改进了授权服务器的访问模式(降低负载,加快检查速度)
- 泄漏访问令牌的访问窗口较短(这些访问令牌很快过期,减少了泄露令牌允许访问受保护资源的机会)
- 滑动会话(见下文)
滑动会话是在一段时间不活动后到期的会话。可以想象,使用访问令牌和刷新令牌可以轻松实现。当用户执行操作时,将发出新的访问令牌。如果用户使用过期的访问令牌,则该会话将被视为非活动状态,并且需要新的访问令牌。是否可以使用刷新令牌获取此令牌或者需要新的身份验证轮次是由开发团队的要求定义的。
废话一堆,简单的来说就是:
服务器生成token的过程中,会有两个时间,一个是token失效时间,一个是token刷新时间,刷新时间肯定比失效时间长,当用户的
token过期时,你可以拿着过期的token去换取新的token,来保持用户的登陆状态,当然你这个过期token的过期时间必须在刷新时间之内,如果超出了刷新时间,那么返回的依旧是 401
所以要实现无痛刷新token,我们应该这样
- 在axios的拦截器中加入token刷新逻辑
- 当用户token过期时,去向服务器请求新的 token
- 把旧的token替换为新的token
- 然后继续用户当前的请求
- 用户体验棒棒哒
上代码
在axios的拦截器中加入token刷新逻辑
instance.interceptors.response.use(
function (response) {
// 对响应数据做点什么
return response.data
},
function (error) {
console.log(error)
if (error.response) {
if (error.response.status === 401) {
// 如果当前路由不是login,并且用户有 “记住密码” 的操作
// 那么去请求新 token
if (router.currentRoute.name !== 'login') {
if (getRemember() && getRefreshToken()) {
return doRequest(error)
} else {
Message.error('登陆过期请重新登陆!')
setToken('')
router.push({
name: 'login'
})
}
}
}
}
// 对响应错误做点什么
return Promise.reject(error.response)
}
)
async function doRequest (error) {
const data = await store.dispatch('refreshToken')
return res
}
// refreshToken 中重新设置了 token 和 refresh_token
commit('setToken', { token, expiresIn })
setRefreshToken(token, refreshTtl / (60 * 60 * 24))
来看测试
为了方便测试,我们手动清除了 token 来造成token 过期的效果
可以看到手动清除token之后,系统自动去refresh了token,而不是跳到登录页面
但是问题又来了
可以看出用户本身要去请求 articles 的接口,并没有再重复请求。请脑补:用户点击了文章列表,但是系统好像 “没反应” ???
所以接下来,我们不仅要刷新token而且要再次发送用户上次的请求
上代码
async function doRequest (error) {
const data = await store.dispatch('refreshToken')
let { token_type: tokenType, access_token: accessToken } = data
let token = tokenType + accessToken
let config = error.response.config
config.headers.Authorization = token
const res = await axios.request(config)
return res
}
这里我们一定要用同步的方法来进行这一系列操作!!(比如 async / await)
本文转载自:https://segmentfault.com/a/1190000017304793
前后端分离中的无痛刷新token机制的更多相关文章
- nodejs--JWT 在前后端分离中的应用与实践
nodejs--JWT 在前后端分离中的应用与实践 http://www.cnblogs.com/lidongyue/p/5269695.html
- shiro vue 前后端分离中模拟登录遇到的坑
系统采用jeeplus框架(ssm+redis+shiro+mongodb+redis),默认是了JSP未做前后端分离,由于业务需要已经多终端使用的需求(H5.小程序等),需要实现前后端分离.但是由于 ...
- 前后端分离中,Gulp实现头尾等公共页面的复用
前言 通常我们所做的一些页面,我们可以从设计图里面看出有一些地方是相同的.例如:头部,底部,侧边栏等等.如果前后端分离时,制作静态页面的同学,对于这些重复的部分只能够通过复制粘贴到新的页面来,如果页面 ...
- JWT 在前后端分离中的应用与实践
关于前后端分离 前后端分离是一个很有趣的议题,它不仅仅是指前后端工程师之间的相互独立的合作分工方式,更是前后端之间开发模式与交互模式的模块化.解耦化.计算机世界的经验告诉我们,对于复杂的事物,模块化总 ...
- 前后端分离中,gulp实现头尾等公共页面的复用 前言
前言 通常我们所做的一些页面,我们可以从设计图里面看出有一些地方是相同的.例如:头部,底部,侧边栏等等.如果前后端分离时,制作静态页面的同学,对于这些重复的部分只能够通过复制粘贴到新的页面来,如果页面 ...
- Vue+SpringBoot前后端分离中的跨域问题
在前后端分离开发中,需要前端调用后端api并进行内容显示,如果前后端开发都在一台主机上,则会由于浏览器的同源策略限制,出现跨域问题(协议.域名.端口号不同等),导致不能正常调用api接口,给开发带来不 ...
- 前后端分离之接口登陆权限token
随着业务的需求普通的springmvc+jsp已经不能满足我们的系统了,会逐渐把后台和前端展示分离开来,下面我们就来把普通的springmvc+jsp分为 springmvc只提供rest接口,前端用 ...
- SpringBootSecurity学习(19)前后端分离版之OAuth2.0 token的存储和管理
内存中存储token 我们来继续授权服务代码的下一个优化.现在授权服务中,token的存储是存储在内存中的,我们使用的是 InMemoryTokenStore : 图中的tokenStore方法支持很 ...
- Springboot前后端分离中,后端拦截器拦截后,前端没有对应的返回码可以判断
项目登录流程如下 用户进入前端登录界面,输入账号密码等,输入完成之后前端发送请求到后端(拦截器不会拦截登录请求),后端验证账号密码等成功之后生成Token并存储到数据库,数据库中包含该Token过期时 ...
随机推荐
- webpack + vuecli多页面打包基于(vue-template-admin)修改
转: webpack + vuecli多页面打包基于(vue-template-admin)修改 遇见的问题TypeError: Cannot read property 'tap' of undef ...
- entitybuilder--一个简单的业务通用框架
关于业务通用框架的思考 业务系统是千差万别的,例如,保存.更新和删除订单,或者保存订单和保存客户,走的根本不是一个流程.但是,它们还是有共同点,它们的流程大致可以分成下面的几个部分: 拿到增删改等操作 ...
- kali msf6 更新及bug处理
问题描述 Metasploit 漏洞库更新,利用msfupdate命令更新,出现已停止该命令更新,出现如下提示: 利用一句话安装更新,命令如下,安装过程中有部分警告出现 curl https://ra ...
- IDEA修改jar包中class文件后重新生成jar包
一.背景 最新想要修改rebeyond大佬的冰蝎项目,特地去网上搜索如何修改jar包中的源码再替换回去的方法,但由于现在的一些文章写的太烂,导致走了很多弯路,因此写下这篇快速使用IDEA修改源码并替换 ...
- 基于es实现一个简单的搜索引擎
一.什么是es Elasticsearch是一个基于ApacheLucene(TM)的开源搜索引擎.无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进.性能最好的.功能最全的搜索引擎库.但 ...
- WPF 基础 - x 名称空间详解
名称 种类(默认Attribute) 备注 x:Array 标记拓展 可作为 ListBox.ItemsSource 的值 x:Class 指定与 .cs 中哪个类合并,所指示的类型在声明时使用 pa ...
- 【linux】Linux删除文件后磁盘依旧占用空间的问题
转自https://blog.51cto.com/2483526/798379 感谢 1.用df 检查发现/根目录可用空间为0 [root@/]#df -h 2.用du检查发现各目录占用的空间都很少, ...
- Python中面向对象的概念
1.语言的分类 1)面向机器 抽象成机器指令,机器容易理解.代表:汇编语言. 2)面向过程 做一件事,排除步骤,第一步做什么,第二步做什么,如果出现A问题,做什么处理,出现b问题,做什么处理.问题规模 ...
- Azure Cost alerts 费用成本分析
一,引言 依稀记得在一月初,我们在 Azure 上做成了一个 费用警报的监控,果不其然,前两天 Azure 给我发了两封封 Azure 预警警报的邮件,提醒我的预算的总费用超过了设置的通知阈值 &qu ...
- P1055_ISBN号码(JAVA语言)
题目描述 每一本正式出版的图书都有一个ISBN号码与之对应,ISBN码包括9位数字.1位识别码和3位分隔符, 其规定格式如x-xxx-xxxxx-x,其中符号-就是分隔符(键盘上的减号), 最后一位是 ...