今天我们来说一说前后端分离中的无痛刷新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种

  1. 存在 cookie 中
  2. 存在 localStorage 中

我觉得都可以,两种我都用

token过期时,前端该怎么处理

思路:token过期处理方式大概就是:

  1. 第一种:跳回登陆页面重新登陆
  2. 第二种:catch 401 ,然后重新获取 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)。另一方面,刷新令牌通常需要检查授权服务器。这种处理授权检查的分割方式允许三件事:

  1. 改进了授权服务器的访问模式(降低负载,加快检查速度)
  2. 泄漏访问令牌的访问窗口较短(这些访问令牌很快过期,减少了泄露令牌允许访问受保护资源的机会)
  3. 滑动会话(见下文)

滑动会话是在一段时间不活动后到期的会话。可以想象,使用访问令牌和刷新令牌可以轻松实现。当用户执行操作时,将发出新的访问令牌。如果用户使用过期的访问令牌,则该会话将被视为非活动状态,并且需要新的访问令牌。是否可以使用刷新令牌获取此令牌或者需要新的身份验证轮次是由开发团队的要求定义的。

上文摘抄自[刷新令牌:何时使用它们以及它们如何与JWT交互

废话一堆,简单的来说就是:

服务器生成token的过程中,会有两个时间,一个是token失效时间,一个是token刷新时间,刷新时间肯定比失效时间长,当用户的   token  过期时,你可以拿着过期的token去换取新的token,来保持用户的登陆状态,当然你这个过期token的过期时间必须在刷新时间之内,如果超出了刷新时间,那么返回的依旧是 401

所以要实现无痛刷新token,我们应该这样

  1. 在axios的拦截器中加入token刷新逻辑
  2. 当用户token过期时,去向服务器请求新的 token
  3. 把旧的token替换为新的token
  4. 然后继续用户当前的请求
  5. 用户体验棒棒哒

上代码

在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机制的更多相关文章

  1. nodejs--JWT 在前后端分离中的应用与实践

    nodejs--JWT 在前后端分离中的应用与实践 http://www.cnblogs.com/lidongyue/p/5269695.html

  2. shiro vue 前后端分离中模拟登录遇到的坑

    系统采用jeeplus框架(ssm+redis+shiro+mongodb+redis),默认是了JSP未做前后端分离,由于业务需要已经多终端使用的需求(H5.小程序等),需要实现前后端分离.但是由于 ...

  3. 前后端分离中,Gulp实现头尾等公共页面的复用

    前言 通常我们所做的一些页面,我们可以从设计图里面看出有一些地方是相同的.例如:头部,底部,侧边栏等等.如果前后端分离时,制作静态页面的同学,对于这些重复的部分只能够通过复制粘贴到新的页面来,如果页面 ...

  4. JWT 在前后端分离中的应用与实践

    关于前后端分离 前后端分离是一个很有趣的议题,它不仅仅是指前后端工程师之间的相互独立的合作分工方式,更是前后端之间开发模式与交互模式的模块化.解耦化.计算机世界的经验告诉我们,对于复杂的事物,模块化总 ...

  5. 前后端分离中,gulp实现头尾等公共页面的复用 前言

    前言 通常我们所做的一些页面,我们可以从设计图里面看出有一些地方是相同的.例如:头部,底部,侧边栏等等.如果前后端分离时,制作静态页面的同学,对于这些重复的部分只能够通过复制粘贴到新的页面来,如果页面 ...

  6. Vue+SpringBoot前后端分离中的跨域问题

    在前后端分离开发中,需要前端调用后端api并进行内容显示,如果前后端开发都在一台主机上,则会由于浏览器的同源策略限制,出现跨域问题(协议.域名.端口号不同等),导致不能正常调用api接口,给开发带来不 ...

  7. 前后端分离之接口登陆权限token

    随着业务的需求普通的springmvc+jsp已经不能满足我们的系统了,会逐渐把后台和前端展示分离开来,下面我们就来把普通的springmvc+jsp分为 springmvc只提供rest接口,前端用 ...

  8. SpringBootSecurity学习(19)前后端分离版之OAuth2.0 token的存储和管理

    内存中存储token 我们来继续授权服务代码的下一个优化.现在授权服务中,token的存储是存储在内存中的,我们使用的是 InMemoryTokenStore : 图中的tokenStore方法支持很 ...

  9. Springboot前后端分离中,后端拦截器拦截后,前端没有对应的返回码可以判断

    项目登录流程如下 用户进入前端登录界面,输入账号密码等,输入完成之后前端发送请求到后端(拦截器不会拦截登录请求),后端验证账号密码等成功之后生成Token并存储到数据库,数据库中包含该Token过期时 ...

随机推荐

  1. Cassandra数据操作管理工具tableplus

    一.概述 Cassandra是一个NoSQL数据库,具有类SQL CQL入口,基本语法与SQL保持一致.其实笔者认为 Cassandra的自带的cqlsh已经满足本的需求:如: 但是用习惯了数据库操作 ...

  2. pytorch中多个loss回传的参数影响示例

    写了一段代码如下: import torch import torch.nn as nn import torch.nn.functional as F class Test(nn.Module): ...

  3. [个人总结]pytorch中model.eval()会对哪些函数有影响?

    来源于知乎:pytorch中model.eval()会对哪些函数有影响? - 蔺笑天的回答 - 知乎 https://www.zhihu.com/question/363144860/answer/9 ...

  4. OSI协议简述版

    OSI简介 OSI只是计算机网络中的一种协议名称缩写,它只是电脑间传输数据的协议,并不代表具体的物理设备,并且这种协议,只是被人为的划分为五层:物理层.数据链路层.网络层.传输层.应用层.记住,它只是 ...

  5. Python基础(1)——变量和数据类型[xiaoshun]

    目录 一.变量 1.概述 Variables are used to store information to be referenced(引用)and manipulated(操作) in a co ...

  6. 【odoo14】odoo 14 Development Cookbook【目录篇】

    网上已经有大佬翻译过odoo12并且在翻译odoo14了.各位着急的可以自行搜索下... 这本书是为了让自己从odoo12转odoo14学习.也是为了锻炼下自己... odoo 14 Developm ...

  7. LAMP环境搭建与配置

    下载mysql 解压 运行错误 下载插件 启动成功 安装Apache 解压 报错  安装插件 再次报错 修改文档 成功 安装插件 下载 安装php 安装完成 解析php 安装完成 虚拟主机(共享主机, ...

  8. IPFS挖矿硬盘满了会怎样?

    IPFS是一个互联网协议,对标现在的HTTP.所以,可以想见未来IPFS有多大的价值.所谓IPFS挖矿,是基于IPFS,挖的是filecoin,称其为filecoin挖矿倒是更为贴切.许多初接触IPF ...

  9. 在Python中创建M x N的数组

    在Python中创建M x N的数组 一般有三种方法: 列表乘法 dp = [[0] * n] * m for 循环 dp= [[0 for _ in range(n)] for _ in range ...

  10. Centos7安装maven详情以及配置

    一.maven安装: 1.获取maven下载地址: 查询maven最新版本地址:https://maven.apache.org/download.cgi 当前最新版本为maven 3.6.3    ...