目前手头的vue项目关于权限一块有一个需求,其实架构师很早就要求我做了,但是由于这个紧急程度不是很高,最近临近项目上线,我才想起,于是赶紧补上这个功能。这个项目是基于OAuth2.0认证,需要在每个请求的头部携带access_token,如果这个access_token过期,需要利用已有的refresh _token去重新获取一个access_token,如果连这个refresh_token也过期了,那就是真正的过期了,需要退出登录页面。refresh_token在获取新的access_token的时候需要让用户无感知,也叫无痛刷新。

  这里的代码实现肯定是要在axios拦截器里写的,但是是在请求拦截器里写还是在响应拦截器里写还是有区别的:

  1.写在请求拦截器里:每次请求之前都会先请求一个checkToken的接口,来确认这个access_token是否过期,如果没有过期,直接就发起原本的请求,如果过期,利用已有的refresh _token去重新获取一个access_token之后,再发起原本的请求。但是这样写有个缺点,就是每次请求之前都要额外请求一次checkToken的接口,如果网速不好,会给用户造成不好的体验,而且对服务器造成了性能上的浪费。

  2.写在响应拦截器里:直到access_token过期,返回401未授权,才利用已有的refresh _token去重新获取一个access_token。

  最后我和后端讨论了下,最后采用了第二种方法,把checkToken放在后端,前端无感知刷新写在响应拦截器里。

这里写的一个响应拦截器:

import axios from 'axios'

//创建一个axios实例
const service = axios.create({
timeout: 5000, // 请求超时时间
withCredentials:true //表示跨域请求时是否需要使用凭证. 默认为false
})
var loading;//遮罩层 // 响应拦截器
service.interceptors.response.use(
response => {
//do what you like
},
error => {
loading.close();
if (error && error.response) {
switch (error.response.status) {
case 400:
error.message = '请求错误'
break
case 401:
return doRequest(error);
case 403:
error.message = '拒绝访问'
break
case 404:
error.message = `请求地址出错: ${error.response.config.url}`
break
case 408:
error.message = '请求超时'
break
case 500:
error.message = '服务器内部错误'
break
case 501:
error.message = '服务未实现'
break
case 502:
error.message = '网关错误'
break
case 503:
error.message = '服务不可用'
break
case 504:
error.message = '网关超时'
break
case 505:
error.message = 'HTTP版本不受支持'
break
default:
break
}
}
errorLog(error)
return Promise.reject(error)
}
)
  export default service
 

  可以看到在响应拦截器的错误回调函数里401值的时候调用了一个方法doRequest();

async function doRequest (error) {
try {
const data = await getNewToken();
var token=data.data.token_type+' '+data.data.access_token;
sessionStorage.setItem('RequestToken',token);
const res = await service.request(error.config)
return res;
} catch(err) {
Message({
message: '登录会话已过期,请重新登录',
type: 'error',
duration: 5 * 1000
})
sessionStorage.clear();
router.replace({
path:"/login"
});
return err;
}
}

  这里的重点这些请求必须是同步的,同步的,同步的,重要的事情说三遍,而axios默认是异步的,所以你要么使用ES6的async/await语句,要么使用then回调函数,必须保持是同步的。而getNewToken()则是利用refresh_token重新获取access_token方法。算了,一并贴出,仅作参考。

import qs from 'qs'

async function getNewToken() {
var refreshToken=sessionStorage.getItem('refreshToken');
return await axios({
url: '/OAuth/oauth/token',
method: 'post',
headers: {
'Authorization': 'Basic XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
'Content-Type':'application/x-www-form-urlencoded'
},
data:qs.stringify({
grant_type:'refresh_token',
refresh_token : refreshToken
})
})
}

  下面看效果。为了效果,这里设置了access_token有效时间为5s,refresh _token有效时间为10s。动图是这样的:

  一步一步分解下,登录的时候,获取到access_token和refresh _token。然后带着access_token:f0a3******cb64去访问menuQuery接口是可以正常请求的。

  但是之后,我等了超过5s后(不超过10s,这个时候access_token已过期,refresh _token未过期)发了一个对0304接口的请求,这个时候返回401未授权,说明access_token:f0a3******cb64已过期。

  这时利用refresh_token重新获取access_token。

  可以看到返回了一个新的access_token:8332******1c8a,于是带着这个新的access_token重新发起对0304接口的请求,这个时候就可以返回所需要的数据。

  之后再等超过5s,这个时候access_token过期了,refresh _token也过期了。动图是这样的:

   这时的请求返回的是400,而不是401了,这说明refresh _token:826b******17d1过期了。这个时候就该退出登录界面,重新登录了。

  最后,放一个总的效果图:

基于OAuth2.0的token无感知刷新的更多相关文章

  1. OAuth2.0与前端无感知token刷新实现

    前言 OAuth是一个关于授权(authorization)的开放网络标准,在全世界得到广泛的应用.Facebook.Twitter和Google等各种在线服务都提供了基于OAuth规范的认证机制. ...

  2. ASP.NET WebApi 基于OAuth2.0实现Token签名认证

    一.课程介绍 明人不说暗话,跟着阿笨一起玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将是我们需要思考的问题.为了保护我们的WebApi数 ...

  3. IdentityServer4之SSO(基于OAuth2.0、OIDC)单点登录、登出

    IdentityServer4之SSO(基于OAuth2.0.OIDC)单点登录.登出 准备  五个Web站点: 1.localhost:5000 :                  认证服务器.2 ...

  4. 基于OAuth2.0的统一身份认证中心设计

    1. 引言 公司经历多年发展后,在内部存在多套信息系统,每套信息系统的作用各不相同,每套系统也都拥有自己独立的账号密码权限体系,这时,每个人员都需要记住不同系统的账号密码,人员入职和离职时,人事部门都 ...

  5. 基于OAuth2.0的第三方认证

    浅显易懂的解释 来源 yahoo OAuth认证 原理 理解OAuth 2.0:原理.分类 一张图搞定OAuth2.0:是什么,怎么用 应用自身,完成用户认证: 缺点: 1.不同的访问Web应用提供不 ...

  6. 基于oauth2.0实现应用的第三方登录

    OAuth2 OAuth2所涉及到的对象主要有以下四个: Client 第三方应用,我们的应用就是一个Client Resource Owner 资源所有者,即用户 Authorization Ser ...

  7. QQ联合登录(基于Oauth2.0协议)

    1. 获取授权码Authorization Code https://graph.qq.com/oauth2.0/authorize?response_type=code&client_id= ...

  8. Spring Cloud云架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)

    上一篇我根据框架中OAuth2.0的使用总结,画了SSO单点登录之OAuth2.0 登出流程,今天我们看一下根据用户token获取yoghurt信息的流程: /** * 根据token获取用户信息 * ...

  9. API开放平台接口设计-------基于OAuth2.0协议方式

    1,简介OAuth http://www.ruanyifeng.com/blog/2019/04/oauth_design.html OAuth 是什么? http://www.ruanyifeng. ...

随机推荐

  1. django 从零开始 5 数据库模型创建

    进入应用项目下的models.py文件 自带一个导入的包 from django.db import models 使用这个包创建models模型 我这是要创建一个图站 ,所以模型设置并不复杂(路径配 ...

  2. django 从零开始 3认识url解析

    在视图函数中定义一个函数abc 接受得到的参数 并显示在页面上 urls中设置 在页面会显示出错误  找不到该url ,原因是django1版本中使用的是url和re_path ,突然django2变 ...

  3. Unsafe中CAS的实现

    前言 Unsafe 是位于 sun.misc 包下的一个类.Unsafe 提供的 API 大致可分为内存操作.CAS.Class 相关.对象操作.线程调度.系统信息获取.内存屏障.数组操作等几类.由于 ...

  4. MySQL 整体架构一览

    MySQL 在整体架构上分为 Server 层和存储引擎层.其中 Server 层,包括连接器.查询缓存.分析器.优化器.执行器等,存储过程.触发器.视图和内置函数都在这层实现.数据引擎层负责数据的存 ...

  5. C++类的详解

    目录 一.类成员的访问权限 二.成员变量的命名 三.构造函数 四.析构函数 五.C++程序也很优雅 六.类的其它知识 七.可变参数 八.课后作业 九.版权声明 超女选秀的例子我们玩了很久,为了学习的需 ...

  6. Echart饼形图和折线图的循环展示及选择展示

    需求:根据不同的入参调同一接口,循环展示一组饼形图或折线图: 主要问题:在于给定的数据格式不符合图表的配置项格式,需要拆分组装数据:首先默认展示几个图表,当选中一个类别,需要展示其中一个的时候,页面中 ...

  7. 032.核心组件-kube-proxy

    一 kube-proxy原理 1.1 kube-proxy概述 Kubernetes为了支持集群的水平扩展.高可用性,抽象出了Service的概念.Service是对一组Pod的抽象,它会根据访问策略 ...

  8. ajax5

    处理跨域方法 (代理) 一个域名地址的组成: /script/jQuery.js 协议    子域名  主域名   端口号  请求资源地址 当协议,子域名,主域名,端口号中任意一个不相同时,都算作不同 ...

  9. 【Weiss】【第03章】练习3.12:单链表倒置

    [练习3.12] a.编写一个非递归过程以O(N)时间反转单链表. b.使用常数附加空间编写一个过程以O(N)时间反转单链表. Answer: 这题的b貌似没啥意义,在a小题里直接用头插法,不断地将头 ...

  10. 使用JDBC工具类模拟登陆验证-Java(新手)

    模拟登陆验证: package JdbcDome; import java.sql.Connection; import java.sql.PreparedStatement; import java ...