https://segmentfault.com/a/1190000008470355?utm_source=tuicool&utm_medium=referral

转 https://www.jianshu.com/p/576dbf44b2ae

重要:转https://www.cnblogs.com/lingnweb/p/9887974.html

vue axios封装以及登录token过期跳转问题  https://blog.csdn.net/H1069495874/article/details/80057107

http://www.51testing.com/html/93/n-4458693-2.html

1.什么是Token 机制?

token的意思是“令牌”,是服务端生成的一串字符串,作为客户端进行请求的一个标识。 当用户第一次登录后,服务器生成一个Token并将此Token返回给客户端,在以后的请求过程中,需要将该Token作为参数或者放在header里面发送给服务器作为身份验证的一个步骤,无需再次带上用户名和密码,但是服务端每隔一段时间(比如30分钟)就会重新生成Token,这时候客户端再用本地缓存的旧Token去请求就无法通过身份认证,一般状态码都会是401。
 

vue项目中token失效处理方法,在main.js配置如下

//判断token失效跳转
axios.interceptors.response.use(response => {
if (response) {
switch (response.data.code) { case 1001: //与后台约定登录失效的返回码,根据实际情况处理
sessionStorage.removeItem('uid'); //删除用户ID
sessionStorage.removeItem('key'); //删除用户登录验证的key值,即token值
router.replace({
path: '/Login',
query: {
redirect: router.currentRoute.fullPath
}
})
}
}
return response;
}, error => { return Promise.reject(error.response.data) //返回接口返回的错误信息
})

token失效后,需用户重新登录才可以继续访问管理后台 

刷新token和token是否过期的操作都是由后端实现,前端只负责根据code的不同状态来做不同的操作:

一、判断token是否过期、失效

举例:一般响应状态码 code :0,表示请求成功。①响应状态码 code:10010表示token过期 ②响应状态码 code:10011 表示token无效。这些状态码都由你自己和后端的同学一起定义。code等于10010和10011这两种状态都会跳转到登录页,重新进行登录并获取最新的token。

二、在一定时间内刷新token

为什么需要刷新token?因为出于安全性的考虑,一般是一天或几个小时更新token,看项目需要。

怎么实现?我和后端的同学是这么定义的,在发送任何一次请求时,如果需要更新token,响应体中后端的同学给我返回了token这个字段,token出现在了响应体中,说明这时候是需要刷新token的(其他非刷新token的请求时是没有token字段的),这时用localStorage保存最新token,自动覆盖掉原来旧的token,这样下次再调用新接口时用的就是最新的token了,这样用户也感知不到token更新的过程。

    

三、具体实现

/**
* 全局变量 和 设置 、配置等。。。
*/ import axios from 'axios' // 引入axios import Storage from '@/assets/js/util/storage.js' // storage工具类,简单的封装 axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded' /* 请求拦截器 */ axios.interceptors.request.use(function (config) { // 每次请求时会从localStorage中获取token let token = Storage.localGet('token') if (token) { token = 'bearer' + ' ' + token.replace(/'|"/g, '') // 把token加入到默认请求参数中 config.headers.common['Authorization'] = token } return config }, function (error) { return Promise.reject(error) }) /* 响应拦截器 */ axios.interceptors.response.use(function (response) { // ①10010 token过期(30天) ②10011 token无效 if (response.data.code === 10010 || response.data.code === 10011) { Storage.localRemove('token') // 删除已经失效或过期的token(不删除也可以,因为登录后覆盖) router.replace({ path: '/login' // 到登录页重新获取token }) } else if (response.data.token) { // 判断token是否存在,如果存在说明需要更新token Storage.localSet('token', response.data.token) // 覆盖原来的token(默认一天刷新一次) } return response }, function (error) { return Promise.reject(error) })

缓存工具类 Storage

var Storage = {
// ==================sessionsTorage设置缓存================
// 设置缓存
sessionSet: function (name, data) {
sessionStorage.removeItem(name)
sessionStorage.setItem(name, JSON.stringify(data))
},
// 获取缓存
sessionGet: function (name) {
return JSON.parse(sessionStorage.getItem(name))
},
// 清除缓存
sessionRemove: function (name) {
sessionStorage.removeItem(name)
},
// ==================localStorage设置缓存==================
// 设置缓存
localSet: function (name, data) {
localStorage.removeItem(name)
localStorage.setItem(name, JSON.stringify(data))
},
// 获取缓存
localGet: function (name) {
return JSON.parse(localStorage.getItem(name))
},
// 清除缓存
localRemove: function (name) {
localStorage.removeItem(name)
} } export default Storage

  

最后,在评论有同学提到并发请求时,因为请求的过程快慢不同,token有可能还是旧的token。所以对于并发请求的情况还是要结合promise来使用

请求时token过期自动刷新token

1.在开发过程中,我们都会接触到token,token的作用是什么呢?主要的作用就是为了安全,用户登陆时,服务器会随机生成一个有时效性的token,用户的每一次请求都需要携带上token,证明其请求的合法性,服务器会验证token,只有通过验证才会返回请求结果。

2.当token失效时,现在的网站一般会做两种处理,一种是跳转到登陆页面让用户重新登陆获取新的token,另外一种就是当检测到请求失效时,网站自动去请求新的token,第二种方式在app保持登陆状态上面用得比较多。

3.下面进入主题,我们请求用的是axios,不管用何种请求方式,刷新token的原理都是一样的。

//封装了一个统一的请求函数,这个不是重点

export default function request(url, options) {
const token = localStorage.getItem('token');
const defaultOptions = {
headers: {
Authorization: `Bearer ${token}`,
},
withCredentials: true,
url: url,
baseURL: BASE_URL,
};
const newOptions = { ...options, ...defaultOptions };
return axios.request(newOptions)
.then(checkStatus)
.catch(error => console.log(error));
}

  

// 封装了一个检测返回结果的函数,与后台返回状态码code === 1002表示token失效

let isRefreshing = true;
function checkStatus(response) {
if (response && response.code === 1002) {
// 刷新token的函数,这需要添加一个开关,防止重复请求
if(isRefreshing){
refreshTokenRequst()
}
isRefreshing = false;
// 这个Promise函数很关键
const retryOriginalRequest = new Promise((resolve) => {
addSubscriber(()=> {
resolve(request(url, options))
})
});
return retryOriginalRequest;
}else{
return response;
}
}

  

// 刷新token的请求函数

function refreshTokenRequst(){
let data;
const refreshToken = localStorage.getItem('refreshToken');
data:{
authorization: 'YXBwYXBpczpaSWxhQUVJdsferTeweERmR1praHk=',
refreshToken,
}
axios.request({
baseURL: BASE_URL,
url:'/app/renewal',
method: 'POST',
data,
}).then((response)=>{
localStorage.setItem('refreshToken',response.data.refreshToken);
localStorage.setItem('token',response.data.token);
onAccessTokenFetched();
isRefreshing = true;
});
}

  

// Promise函数集合

let subscribers = [];
function onAccessTokenFetched() {
subscribers.forEach((callback)=>{
callback();
})
subscribers = [];
} function addSubscriber(callback) {
subscribers.push(callback)
}

  

总结:其实token失效,自动刷新token,在页面只有一个请求的时候是比较好处理的,但是如果页面同时有多个请求,并且都会产生token失效,这就需要一些稍微复杂的处理,解决方式主要是用了Promise 函数来进行处理。每一个token失效的请求都会存到一个Promise函数集合里面,当刷新token的函数执行完毕后,才会批量执行这些Promise函数,返回请求结果。还有一点要注意一下,这儿设置一个刷新token的开关isRefreshing,这个是非常有必要的,防止重复请求。

必备技能四、ajax及token的更多相关文章

  1. Android高工必备技能

    转载:http://www.jianshu.com/p/d791bbede02c Step 1. 玩转RxJava 使用RxJava处理异步极其方便,各种操作符可以对数据做流水线式操作,再加上与Ret ...

  2. 高级Linux运维工程师必备技能(扫盲篇)

    高级Linux运维工程师必备技能(扫盲篇) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在了解文件系统之前,我们要学习一下磁盘存储数据的方式,大家都知道文件从内存若要持久化存储的 ...

  3. 百度Hr分享,一个合格的数据工程师简历中必备技能?

    如果你是一名数据科学方面的求职者,你肯定想知道在简历上写些什么才能获得面试的机会:如果你想进入这个领域,你一定想知道具备哪些技术才能成为一名有竞争力的求职者. 在本文中,我们对Indeed中一千份数据 ...

  4. Java1.7的HashMap源码分析-面试必备技能

    HashMap是现在用的最多的map,HashMap的源码可以说是面试必备技能,今天我们试着分析一下jdk1.7下的源码. 先说结论:数组加链表 一.先看整体的数据结构 首先我们注意到数据是存放在一个 ...

  5. 详解linux运维工程师入门级必备技能

    详解linux运维工程师入门级必备技能 | 浏览:659 | 更新:2013-12-24 23:23 | 标签:linux it自动化运维就是要很方便的运用各种工具进行管理维护,有效的实施服务器保护 ...

  6. 自动化部署必备技能—部署yum仓库、定制rpm包

    部署yum仓库.定制rpm包 目录 第1章 扩展 - yum缓存 1.1 yum缓存使用步骤... 1 1.1.1 导言... 1 1.1.2 修改配置文件... 1 1.1.3 使用缓存... 1 ...

  7. 【转帖】系统软件工程师必备技能-进程内存的working set size(WSS)测量

    系统软件工程师必备技能-进程内存的working set size(WSS)测量 2018年12月28日 18:43:01 Linuxer_ 阅读数:145 https://blog.csdn.net ...

  8. SQL Server管理员必备技能之性能优化

    SQL Server管理员必备技能之性能优化 高文龙关注1人评论1171人阅读2017-09-22 08:27:41 SQL Server 作为企业必不可少的服务之一,所以对于管理员的日常运维是一个极 ...

  9. 我的前端工具集(六)Ajax封装token

    我的前端工具集(六)Ajax封装token   liuyuhang原创,未经允许禁止转载 在单点登陆中,或登陆验证后,不应该每次都验证用户名和密码, 也不应该将用户名密码存入cookie中(虽然很多都 ...

随机推荐

  1. python之time模块和hashlib模块

    一.time模块 import time print(time.strftime('%Y-%m-%d %H:%M:%S'))#获取当前的格式化时间,time.strftime(format) prin ...

  2. android流式布局、待办事项应用、贝塞尔曲线、MVP+Rxjava+Retrofit、艺术图片应用等源码

    Android精选源码 android模仿淘宝首页效果源码 一款艺术图片应用,采用T-MVVM打造 Android MVP + RxJava + Retrofit项目 android流式布局实现热门标 ...

  3. 4)在url中加上a分发参数,用来选哪一个函数

    文件关系目录展示: 然后代码改动部分展示: zixun.controller.class.php <?php //header('Content-type:text/html;charset=u ...

  4. Qt 添加Includes、Libraries库

    1 #------------------------------------------------- # # 加载相机SDK-Includes-Libraries # #------------- ...

  5. mybatis generator 使用教程(生成带注释的实体类)

    引言: 最近的一个项目,由于数据库表巨多,导致需要创建N多个java实体.dao.mapper.xml映射文件,如果均使用纯手工编写,无疑需要耗费大量时间和精力.于是上网学习了mybatis gene ...

  6. linux有些sh文件,为什么要用 ./ 来执行

    因为有环境变量PATH,里面包含了许多目录,这些目录下的可执行文件就无需输入完整路径来执行.你可以用 echo "$PATH"查看当前的环境变量包含的目录,自带的命令文件都是在PA ...

  7. Hexo博客部署

    前些天使用wordpress程序搭建了个人网站,但感觉太重比较适合个人空间,所以这次介绍Hexo搭建免费博客,先提供官网给大家英文版的请点击这里,中文版的请点击这里,在安装一个Git,再是github ...

  8. CDC与HDC的区别以及相互转换

    CDC是MFC的DC的一个类  HDC是DC的句柄,API中的一个类似指针的数据类型.  MFC类的前缀都是C开头的  H开头的大多数是句柄  这是为了助记,是编程读\写代码的好的习惯.  CDC中所 ...

  9. 有用户及目录判断的删除文件内容的Shell脚本

    [root@localhost Qingchu]# cat Qingchu_version2.sh #!/bin/bash #描述: # 清除脚本! #作者:孤舟点点 #版本:2.0 #创建时间:-- ...

  10. Jenkins之邮件通知

    Jenkins默认有一个邮件通知功能,但功能比较单一,能自定义的东西很少,一般使用Extended E-mail Notification插件来发送邮件,EXT Email插件功能比较多,但设置也比较 ...