前言
上一篇我们详细解读了token实现,有一个问题:如果token过期失效时间设置过长,安全性得不到保障;如果token过期失效时间设置过短,会经常需要重新登录来获取新的token,用户体验很差。为了解决这个问题,一个常用的做法就是无感刷新token,那么如何实现无感刷新token呢?
一、实现方案
我们可以使用两个token,一个普通token,另一个刷新token。普通token就是以前所用的token,它的过期失效时间短,比如10分钟;刷新token就是调用刷新token请求带的token,它的过期失效时间长,比如1天。然后我们增加一个接口,用来获取新的普通token,此时普通token已经失效无法使用了,所以这个请求需要带刷新token鉴权。除了刷新token请求,其它请求都需要带普通token鉴权,如果返回401鉴权失败,那就调用刷新token请求获取新的token,然后重新发起请求。这样就相当于普通token每10分钟更新一次,提高了安全性,但是用户又感知不到,不会影响使用体验。
二、接口修改
1.登录接口修改
原来登录接口响应格式如下:
修改后登录接口响应数据样例:
{
“code”: 0,
“message”: “操作成功”,
“data”: {
“refresh_token”: “eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGFpbXMiOnsiaWQiOjEsInVzZXJuYW1lIjoiYWRtaW4ifSwiZXhwIjoxNzIxNDM1NTk5fQ.xEAkreOKNCRLIqbc4Dwm9kL1yQ4URkC21t-SzWDLxMQ”,
“token”: “eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGFpbXMiOnsiaWQiOjEsInVzZXJuYW1lIjoiYWRtaW4ifSwiZXhwIjoxNzIxNDM1NTk5fQ.R-Gjt4rGeaAGnBrJPULRXPcJzX6koKn6FnHvluAyqQ4”
}
}
这里data直接返回json格式,是为了方便前端处理。
2.刷新token接口增加
2.1、基本信息
请求路径:/user/refresh_token
请求方式:GET
接口描述:该接口用于获取新的token
2.2、请求参数
无
2.3、响应数据
响应数据类型:application/json
响应参数说明:
名称 | 类型 | 是否必须 | 默认值 | 备注 | 其他信息 |
---|---|---|---|---|---|
code | number | 必须 | 响应码, 0-成功,1-失败 | ||
message | string | 非必须 | 提示信息 | ||
data | string | 必须 | 返回的数据,json格式,带token和refresh_token |
响应数据样例:
{
“code”: 0,
“message”: “操作成功”,
“data”: {
“refresh_token”: “eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGFpbXMiOnsiaWQiOjEsInVzZXJuYW1lIjoiYWRtaW4ifSwiZXhwIjoxNzIxNDM1Nzk0fQ.sp827OGEFGgYVUDU4wsdr8JPBNWs5ANHD4F4wMf78SA”,
“token”: “eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJjbGFpbXMiOnsiaWQiOjEsInVzZXJuYW1lIjoiYWRtaW4ifSwiZXhwIjoxNzIxNDM1Nzk0fQ.58CsmXUYzsp-ewA_hmTMOvdr-MLB-uSkTOjmJ-mjxNM”
}
}
2.4、备注说明
刷新token接口只返回普通token也可以,但是这样的话如果刷新token也失效就需要重新登录。这里把两个token都重新刷新一下返回,那么只要在刷新token失效时间内有请求操作,刷新token就永远不会失效。当然如果在刷新token失效时间内没有任何请求操作,那么就需要回到登录页面重新登录。
三、后端代码修改
1、登录接口函数修改
if (Md5Util.getMD5String(password).equals(loginUser.getPassword())) {
//登录成功
Map<String, Object> claims = new HashMap<>();
claims.put("id", loginUser.getId());
claims.put("username", loginUser.getUsername());
String token = JwtUtil.genToken(claims);
//String refresh_token = JwtUtil.genToken(claims);
String refresh_token = JwtUtil.genRefreshToken(claims)