前后端分离中的无痛刷新token机制

2023-05-16

今天我们来说一说前后端分离中的无痛刷新token机制,在手机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 过期的效果

1

可以看到手动清除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)

来看演示?

2

到此就结束了,相信大佬们一定都懂了吧?

来自努力成为全栈的后端程序员的博客
大佬绕道,今年刚毕业的新人瑟瑟发抖

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

前后端分离中的无痛刷新token机制 的相关文章

  • 【SpringBoot】面试必杀技-泰山陨石坠,SpringBoot中主启动类的run方法启动流程是什么?

    开头导语由Chatgpt完成 当今互联网行业中 xff0c Java后端开发岗位的竞争异常激烈 xff0c 对于面试者来说 xff0c 掌握一些技巧和知识点将有助于脱颖而出 而对于SpringBoot框架的使用和运行机制 xff0c 更是J
  • node 爬虫,使用 Google puppeteer 抓取 One一个 的网页数据

    puppeteer 就不多介绍了 xff0c 就是一个无界面化的谷歌浏览器 作者本人是前端 xff0c 后端方面的知识不太擅长 xff0c 感觉漏洞还是蛮多的 本教程是作者见猎心喜然后把玩了一下写的 xff0c 有不合理的地方还请包涵 爬虫
  • 微信指纹支付原理浅析

    微信指纹支付从设备出厂到完成支付大致可以分成4个步骤 3对公私钥 xff1a 1 设备出厂公私钥及tee适配 手机厂商在手机tee的RPMB区域内置私钥A priv及微信支付的特定ta和SoterKeyStore xff0c 然后厂商统一将
  • 三极管打造树莓派温控风扇

    为了防止树莓派长时间开机运转温度过高导致触发过热关机 xff0c 很多人都给装了散热风扇 xff0c 但某宝买的风扇插上之后是随着开机一直运转的 xff0c 不能随温度变化而自动开闭 xff0c 很多时候做无用功浪费电且产生噪音 本文将以一
  • PostgreSQL 辟谣存在任意代码执行漏洞:消息不实

    开发四年只会写业务代码 xff0c 分布式高并发都不会还做程序员 xff1f gt gt gt 近期在互联网媒体上流传 PostgreSQL 存在任意代码执行的漏洞 xff1a 拥有 pg read server files 权限的攻击者可
  • vue slot撸一撸

    为什么80 的码农都做不了架构师 xff1f gt gt gt vue使用过程中接触到slot xff0c 一番操作下有以下记录 xff1a 单个 xff1a 父组件引用子组件的时候 xff0c 写在子组件中的内容插入到了子组件中的slot
  • Nmap扫描结果的保存和输出

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 选项解释 oN标准保存 oXXML保存 oGGrep保存 oA保存到所有格式 append output补充保存文件 选项 oG 将结果Grep保存 nmap F oG t
  • SQL岗位30个面试题,SQL面试问题及答案

    SQL岗位30个面试题 xff0c SQL面试问题及答案 xff1a 什么是SQL xff1f SQL xff08 结构化查询语言 xff09 是一种设计用于检索和操作数据的数据库 它属于美国国家标准协会 xff08 ANSI xff09
  • nginx搭建点播视频(Mp4播放)

    首先 xff0c 环境中必然要有gcc c 43 43 环境 yum y install gcc c 43 43 1 使用openresty 这里使用的是1 11 2 1版本的openresty和1 0 2版本的openssl root 6
  • ajax提交 的编码小结

    今天用ajax的post方法提交数据给webservice 由于有email的缘故发现 注册方法调用总是报错 打开报文一看提交的 发现 64 符号被变成了 40 abc 64 126 com 即abc 40126 com 开始我还以为他没有
  • [JavaScript]Cookie详解(转)

    cookie概述 假如利用一个不变的框架来存储购物栏数据 xff0c 而商品显示页面是不断变化的 xff0c 尽管这样能达到一个模拟全局变量的功能 xff0c 但并不严谨 例如在导航框架页面内右击 xff0c 单击快捷菜单中的 刷新 命令
  • 面试组合技-月色血风暴,什么是Spring中的循环依赖?怎么解决循环依赖?

    x1f484 x1f484 x1f484 今年的铜三铁四到了 xff0c 给大家写几篇面试题解析 文章目录 x1f460 什么是Spring中的循环依赖 xff1f x1f462 Spring怎么解决循环依赖 xff1f x1f455 流程
  • matlab练习程序(矩阵生成有向网络图)

    早知道有向图和无向图差别没有想象中的大我就写到一起了 函数中使用的arrow画箭头函数是在这个网站下的 函数名netplot 使用方法输入请help netplot 无返回值 函数只能处理有向图 作者 xff1a tiandsp 最后修改
  • 字符串处理memchr和memrchr

    memchr extern void memchr const void buf int ch size t count 功能 xff1a 从buf所指内存区域的前count个字节查找字符ch 说明 xff1a 当第一次遇到字符ch时停止查
  • 计算多轴飞行器最大悬停时间

    以结果为导向 xff1a 先看下面截图 为了方便看清楚 xff0c 下面截图承接上面截图的 悬停时间公式 xff1a 电池容量 每个电机总电流之和 61 悬停时间 以上面第一个为例 电池容量为22000maH 每个电机总电流之和是什么意思呢
  • linux应用之make命令详解

    从源代码安装过软件的朋友一定对 configure amp amp make amp amp make install 安装三步曲非常熟悉了 然而究竟这个过程中的每一步幕后都发生了些什么呢 xff1f 今天小编将带你一探究竟 深入理解这个过
  • github 之 下载历史版本

    1 打开github中要下载的项目 2 点击commits 点击上图中标记的地方 xff0c 进入下图所示 xff1a 3 选择列表中的某个版本 4 Browse Files 5 下载 点击上图中的 Download ZIP 下载 转载于
  • Linux环境C程序设计(第2版)

    2019独角兽企业重金招聘Python工程师标准 gt gt gt Linux 环境 C 程序设计 xff08 第 2 版 xff09 共分 6 篇 第 1 篇 介绍了 Linux 系统的安装及 LinuxC 开发环境的搭建等 xff1b
  • 如何准备校招技术面试

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 如何准备校招技术面试 标签 xff1a 面试 TOC 2017 年互联网校招已近尾声 xff0c 作为一个非 CS 专业的应届生 xff0c 零 ACM 经验 零期刊论文发
  • vscode添加prettier格式化自动加分号问题

    在vscode的settings json中添加 xff1a 34 prettier singleQuote 34 true 34 prettier semi 34 false 不管别人有没有用 xff0c lz没用 切实有效 xff1a

随机推荐