前言

在前后端分离的开发模式下,前端用户登录成功后后端服务会给用户颁发一个 jwt token。前端(如 vue)在接收到 jwt token 后会将 token 存储到 LocalStorage 中。

后续每次请求都会将此 token 放在请求头中传递到后端服务,后端服务会有一个过滤器对 token 进行拦截校验,校验 token 是否过期,如果 token 过期则会让前端跳转到登录页面重新登录。

因为 jwt token 中一般会包含用户的基础信息,为了保证 token 的安全性,一般会将 token 的过期时间设置的比较短。

但是这样又会导致前端用户需要频繁登录(token 过期),甚至有的表单比较复杂,前端用户在填写表单时需要思考较长时间,等真正提交表单时后端校验发现 token 过期失效了不得不跳转到登录页面。

如果真发生了这种情况前端用户肯定是要骂人的,用户体验非常不友好。本篇内容就是在前端用户无感知的情况下实现 token 的自动续期,避免频繁登录、表单填写内容丢失情况的发生。

实现原理

jwt token 自动续期的实现原理如下:

登录成功后将用户生成的 jwt token 作为 key、value 存储到 cache 缓存里面 (这时候 key、value 值一样),将缓存有效期设置为 token 有效时间的 2 倍。

当该用户再次请求时,通过后端的一个 jwt Filter 校验前端 token 是否是有效 token,如果 token 无效表明是非法请求,直接抛出异常即可;

根据规则取出 cache token,判断 cache token 是否存在,此时主要分以下几种情况:

cache token 不存在

这种情况表明该用户账户空闲超时,返回用户信息已失效,请重新登录。

cache token 存在,则需要使用 jwt 工具类验证该 cache token 是否过期超时,不过期无需处理。

过期则表示该用户一直在操作只是 token 失效了,后端程序会给 token 对应的 key 映射的 value 值重新生成 jwt token 并覆盖 value 值,该缓存生命周期重新计算。

实现逻辑的核心原理:

前端请求 Header 中设置的 token 保持不变,校验有效性以缓存中的 token 为准。

代码实现(伪码)

登录成功后给用户签发 token,并设置 token 的有效期

...

SysUser sysUser = userService.getUser(username,password);

if(null !== sysUser){

String token = JwtUtil.sign(sysUser.getUsername(),

sysUser.getPassword());

}

...

public static String sign(String username, String secret) {

//设置token有效期为30分钟Date date = new Date(System.currentTimeMillis() + 30 * 60 * 1000);

//使用HS256生成token,密钥则是用户的密码Algorithm algorithm = Algorithm.HMAC256(secret);

// 附带username信息return JWT.create().withClaim("username", username).withExpiresAt(date).sign(algorithm);

}

将 token 存入 Redis,并设定过期时间,将 Redis 的过期时间设置成 token 过期时间的两倍

Sting tokenKey = "sys:user:token" + token;

redisUtil.set(tokenKey, token);

redisUtil.expire(tokenKey, 30 * 60 * 2);

过滤器校验 token,校验 token 有效性

public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {

//从header中获取tokenString token = httpServletRequest.getHeader("token")

if(null == token){

throw new RuntimeException("illegal request,token is necessary!")

}

//解析token获取用户名String username = JwtUtil.getUsername(token);

//根据用户名获取用户实体,在实际开发中从redis取User user = userService.findByUser(username);

if(null == user){

throw new RuntimeException("illegal request,token is Invalid!")

}

//校验token是否失效,自动续期if(!refreshToken(token,username,user.getPassword())){

throw new RuntimeException("illegal request,token is expired!")

}

...

}

实现 token 的自动续期

public boolean refreshToken(String token, String userName, String passWord) {

Sting tokenKey = "sys:user:token" + token ;

String cacheToken = String.valueOf(redisUtil.get(tokenKey));

if (StringUtils.isNotEmpty(cacheToken)) {

// 校验token有效性,注意需要校验的是缓存中的tokenif (!JwtUtil.verify(cacheToken, userName, passWord)) {

String newToken = JwtUtil.sign(userName, passWord);

// 设置超时时间redisUtil.set(tokenKey, newToken) ;

redisUtil.expire(tokenKey, 30 * 60 * 2);

}

return true;

}

return false;

}

...

public static boolean verify(String token, String username, String secret) {

try {

// 根据密码生成JWT效验器Algorithm algorithm = Algorithm.HMAC256(secret);

JWTVerifier verifier = JWT.require(algorithm).withClaim("username", username).build();

// 效验TOKENDecodedJWT jwt = verifier.verify(token);

return true;

} catch (Exception exception) {

return false;

}

}

本文中 jwt 的相关操作是基于 com.auth0.java-jwt 实现,大家可以通过阅读原文获取 JWTUtil 工具类。

小结

jwt token 实现逻辑的核心原理是 前端请求 Header 中设置的 token 保持不变,校验有效性以缓存中的 token 为准,千万不要直接校验 Header 中的 token。实现原理部分大家好好体会一下,思路比实现更重要!

JwtUtil

public class JwtUtil {

// Token过期时间30分钟(用户登录过期时间是此时间的两倍,以token在reids缓存时间为准)public static final long EXPIRE_TIME = 30 * 60 * 1000;

/*** 校验token是否正确* @param token 密钥* @param secret 用户的密码* @return 是否正确*/

public static boolean verify(String token, String username, String secret) {

try {

// 根据密码生成JWT效验器Algorithm algorithm = Algorithm.HMAC256(secret);

JWTVerifier verifier = JWT.require(algorithm).withClaim("username", username).build();

// 效验TOKENDecodedJWT jwt = verifier.verify(token);

return true;

} catch (Exception exception) {

return false;

}

}

/*** 获得token中的信息无需secret解密也能获得* @return token中包含的用户名*/

public static String getUsername(String token) {

try {

DecodedJWT jwt = JWT.decode(token);

return jwt.getClaim("username").asString();

} catch (JWTDecodeException e) {

return null;

}

}

/*** 生成签名,30min后过期*/

public static String sign(String username, String secret) {

Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);

//使用HS256生成token,密钥则是用户的密码Algorithm algorithm = Algorithm.HMAC256(secret);

// 附带username信息return JWT.create().withClaim("username", username).withExpiresAt(date).sign(algorithm);

}

/*** 根据request中的token获取用户账号* @param request* @return*/

public static String getUserNameByToken(HttpServletRequest request) {

String accessToken = request.getHeader("X-Access-Token");

String username = getUsername(accessToken);

if (StringUtils.isEmpty(username)) {

throw new RuntimeException("无法获取有效用户!");

}

return username;

}

}

jwt的token自动续约_关于 JWT Token 自动续期的解决方案相关推荐

  1. jwt的token自动续约_JWT(JSON Web Token)自动延长到期时间

    cchamberlain.. 6 如果您使用的是节点(React/Redux/Universal JS),则可以安装npm i -S jwt-autorefresh. 此库根据用户计算的访问令牌到期之 ...

  2. 苹果手机如何关闭自动续费_手机APP会员自动续费怎么办?教你一招快速关闭!...

    做最有趣有料的科技自媒体 你们知道学霸君每个月最讨厌收到什么短信吗? 就是APP自动续费的短信.... 特别是有一些软件,明明百八年前就已经没用了 当时只是因为年少无知觉得会员包月续费开通会比较便宜, ...

  3. 怎么取消苹果手机自动续费_苹果怎样关闭自动续费

    ios取消自动续费可以通过点击设置-iTunes Store 与 App Store-Apple ID-订阅-取消订阅即可.具体可以通过以下步骤操作来实现: 1.在苹果手机桌面点击设置图标进入,如下图 ...

  4. 怎么取消苹果手机自动续费_苹果怎么取消自动续费?官方给的取消流程,速看!...

    苹果怎么取消自动续费?相信大家在充值各类会员或者购买应用的时候都有遇到过自动扣费的情况,想要取消这种自动扣费,担心自己的资金安全想要关闭扣费服务要怎么操作?首先需要我们明确的一点是,除非我们取消订阅, ...

  5. 怎么取消苹果手机自动续费_苹果手机被订阅自动续费了怎么办 苹果退款

    很多人都会遇到这种情况,自己的苹果手机,总是会莫名其妙的被扣走一些费用,这些自动扣费其实是你账户里面的订阅扣费. 什么是订阅扣费?订阅扣费就是你账户里面有订阅项目,到期自动扣除下一个订阅期费用.很多人 ...

  6. 苹果手机如何关闭自动续费_手机APP总自动续费?教你一招关闭它!

    大家晚上好,我是机哥~ 在我们日常使用App的时候,经常就会订阅一些服务,比如想看视频,要在某网站开通一个月的会员服务,可是这些服务,有时候会连续包月的进行付费. 也就是说你订阅了,就会每月的自动扣钱 ...

  7. 怎么取消苹果手机自动续费_手机 App 自动续费套路多?我们要如何取消?

    哈喽大家好,欢迎来到瞎玩科技! 现在很多 App 套路很深,我就想包一个月的会员试试,结果莫名其妙的发现手机上每个月都收到自动续费的通知. 都上人民日报了 最关键的,想解除自动续费,在 App 里找了 ...

  8. 苹果app取消自动续费_自动续费难取消、广告还得看,你为App会员套路充过多少值...

    欢迎点击上面ZAKER关注 日前,网剧<庆余年>热播,腾讯视频.爱奇艺玩起超前点播的 " 骚操作 ",在 VIP 抢先看 6 集的基础上,VIP 会员再交 50 元可在 ...

  9. 如何关闭苹果手机自动扣费_苹果怎样关闭自动续费

    我们在使用苹果手机的时候,会发现很多的软件是有自动续费服务的,比如我们的音乐,比如我们的视频网站等等都是有自动续费的,那么怎么取消呢?下面就来简单介绍一下苹果怎样关闭自动续费. 苹果怎样关闭自动续费? ...

  10. php实现自动续费功能,如何关闭wps自动续费

    微信中,打开"支付管理"界面,点击"自动扣费":然后找到"wps自动续费"项,点击进入:最后点击"关闭服务"即可.支付宝 ...

最新文章

  1. 【CNN】一文读懂卷积神经网络CNN
  2. linux 桌面管理器 xfce 用户自动登录
  3. mx51 uboot启动感悟
  4. ID3和C4.5分类决策树算法 - 数据挖掘算法(7)
  5. java编译时注解_简单介绍 Java 中的编译时注解
  6. Linux内存管理(一)——从硬件角度看内存管理
  7. iOS 13.2“杀后台”严重 被用户狂喷:专业“杀微信”
  8. TheWorld不能访问Taobao的解决办法
  9. 子慕谈设计模式系列(一)
  10. 队列:先进先出的线性表,如何实现增删查?
  11. Obsidian使用手册
  12. jquery获取选中和未选中的checkbox复选框
  13. 关闭Windows Defender工具
  14. 渗透测试-业务逻辑与非常规漏洞原理与利用
  15. 微信小程序:页面有内容却不显示原因
  16. java protobuffer序列化_Java数据通讯中使用Googgle Protobuf 序列化与反序列化
  17. 计算机内部为什么采用二进制表示数据,计算机内部为什么使用二进制处理数据? - 问答库...
  18. Netty处理TCP半包和粘包问题
  19. 关于发短信的软件(zz)
  20. 【Python】and和or的讲解与实例

热门文章

  1. 模型转换:pth转onnx
  2. 《操作系统真象还原》第三章 ---- 完善MBR 尝汇编先苦涩后甘甜而再战MBR!(内有闲聊)
  3. 三国杀服务器维修,三国杀云服务器
  4. 2020年06月16日_万金油_新浪博客
  5. Ubuntu安装N卡驱动
  6. 计算机科学班会,计算机科学与技术学院20级13班召开“砥砺前行,“计”往开来”主题班会...
  7. 首都师范 博弈论 5 2 1帕累托最优
  8. 矩阵行列式的计算及逆矩阵转换
  9. win7系统如何恢复或重装IE8浏览器呢?
  10. c语言编程三角形面积计算,c语言计算三角形面积代码