java无感知重启_基于OAuth2.0的token无感知刷新

本文介绍了在Vue项目中基于OAuth2.0实现token无感知刷新的过程。当access_token过期时,通过refresh_token在响应拦截器中获取新token,确保用户体验不受影响。详细阐述了在请求拦截器和响应拦截器中实现的区别,并提供了具体的axios拦截器代码示例。
摘要由CSDN通过智能技术生成

目前手头的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。动图是这样的:

8201fb0849db60dcb1ee9e8cc855e62d.gif

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

da2b9c85e814803de1e573f23409fc91.png

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

a84002be26fdcc7084f6d470fff0bbe3.png

5db3913d06bc11ecb897959fc1041736.png

这时利用refresh_token重新获取access_token。

52ce614e6f0db1676622507fd5889d83.png

c574fa3df1ee89693d4d2d6a4f03f7d4.png

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

c781e3be9b9e1cc4c70db890f7cec7c5.png

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

1737bd24c8671af2e6bffcbc24ef0246.gif

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

8f1acada74ef4c3ec1743e511618a0db.png

6b391a9489160e18ed6d5803fcbca7c2.png

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

5d9462d563355d2821763a1da4a88f24.gif

b739ec46bb5c46d9c0aa4ce35ba1ea56.png

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[基于OAuth2.0的token无感知刷新]http://www.zyiz.net/tech/detail-126074.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值