JWT如何解析过期的token中的信息

本文涉及的产品
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: JWT如何解析过期的token中的信息

 一、问题背景

  最近搭建springcloud的项目,项目采取了Jwt + spring security 来进行登录验证,Jwt token 锁定用户的失效时间,但是由于 jwt token特性导致token失效时间无法刷新,所以必须新创建一个token令牌,用来代替之前已失效token。

  (token失效时间无法刷新的原因是由于jwt创建token是根据jwt保存的相关信息来计算的,过期时间是其中的一个计算维度,所以一旦过期时间改了,那么生成的token值也就变了。)

  之后为了解决这个问题,结合了redis,将token值保存到redis中,用户操作后刷新redis的有效时间,这样如果jwt token失效了,再检查 redis 中保存token的key是否失效,如果没有失效,那么就重新创建jwt token ,失效了,就重新登录。

  我用一个过期token去调用接口,返回请求未授权。我查看token拦截的方法,发现是token解析异常,返回null导致接口返回未授权。token解析的最终处理都是parseJWT(jsonWebToken)这个方法,代码如下:

public static Claims parseJWT(String jsonWebToken) {
        try {
            return Jwts.parser().setSigningKey(Base64.getDecoder().decode(getBase64Security())).parseClaimsJws(jsonWebToken).getBody();
        } catch (Exception var2) {
            return null;
        }
    }

image.gif

二、问题原因

根据报错堆栈信息找到了DefaultJwtParser类中,找到了问题的原因。

传入过期token,debug调试发现是在DefaultJwtParser的parse(String jwt)方法中返回了ExpiredJwtException 过期异常。部分代码如下

boolean allowSkew = this.allowedClockSkewMillis > 0L;
                if (claims != null) {
                    Date now = this.clock.now();
                    long nowTime = now.getTime();
                    Date exp = claims.getExpiration();
                    String nbfVal;
                    SimpleDateFormat sdf;
                    if (exp != null) {
                        long maxTime = nowTime - this.allowedClockSkewMillis;
                        Date max = allowSkew ? new Date(maxTime) : now;
                        if (max.after(exp)) {
                            sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
                            String expVal = sdf.format(exp);
                            nbfVal = sdf.format(now);
                            long differenceMillis = maxTime - exp.getTime();
                            String msg = "JWT expired at " + expVal + ". Current time: " + nbfVal + ", a difference of " + differenceMillis + " milliseconds.  Allowed clock skew: " + this.allowedClockSkewMillis + " milliseconds.";
                            throw new ExpiredJwtException((Header)header, claims, msg);
                        }
                    }
                    Date nbf = claims.getNotBefore();
                    if (nbf != null) {
                        long minTime = nowTime + this.allowedClockSkewMillis;
                        Date min = allowSkew ? new Date(minTime) : now;
                        if (min.before(nbf)) {
                            sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
                            nbfVal = sdf.format(nbf);
                            String nowVal = sdf.format(now);
                            long differenceMillis = nbf.getTime() - minTime;
                            String msg = "JWT must not be accepted before " + nbfVal + ". Current time: " + nowVal + ", a difference of " + differenceMillis + " milliseconds.  Allowed clock skew: " + this.allowedClockSkewMillis + " milliseconds.";
                            throw new PrematureJwtException((Header)header, claims, msg);
                        }
                    }
                    this.validateExpectedClaims((Header)header, claims);
                }

image.gif

看到结尾的throw new ExpiredJwtException,我相信就找到了问题的关键,原来在在解析token并发现这个token已经过期了,它作出的反应是直接抛异常。

image.gif编辑

异常定义的构造方法中除了msg信息,还有claims和header信息。

检查claims发现,在异常之前token其实已经解析完毕。

这样也就代表着,抛出的这个异常 ExpiredJwtException 中有一个参数 claims 就是解析后的token,那么本次这个问题也就解决了。

  catch ExpiredJwtException 异常后,直接从异常中获取解析的数据即可。

三、方法处理

修改原来的parseJWT(jsonWebToken),代码如下:

public static Claims parseJWT(String jsonWebToken) {
        try {
            return Jwts.parser().setSigningKey(Base64.getDecoder().decode(getBase64Security())).parseClaimsJws(jsonWebToken).getBody();
        } catch (ExpiredJwtException var) {
            return  var.getClaims();
        } catch (PrematureJwtException var1) {
            return var1.getClaims();
        } catch (Exception var2) {
            return null;
        }
    }

image.gif

ExpiredJwtException 异常是超过token过期时间异常

PrematureJwtException 异常是早于token生效时间异议

附带判断token是否过期的方法代码:

public Boolean isTokenExpired(String token) {
        //不管是否过期,都返回claims对象
        Claims claims = parseJWT(token);
        Date expiration = claims.getExpiration();
        //和当前时间进行对比来判断是否过期
        return new Date(System.currentTimeMillis()).after(expiration);
    }

image.gif

最终测试,可以从过期的token中获取用户信息了,接口也不拦截过期token了(因为之间的拦截器代码是根据token能不能解析用户信息去拦截的)。


相关文章
|
3月前
|
存储 前端开发 JavaScript
Cookie、Session、Token、JWT 是什么?万字图解带你一次搞懂!看完这篇,你连老奶奶都能教
HTTP 协议是无状态的,就像一个“健忘”的银行柜员,每次请求都像第一次见面。为解决这一问题,常用的技术包括 Cookie、Session 和 Token。Cookie 是浏览器存储的小数据,Session 将数据存在服务器,Token(如 JWT)则是自包含的无状态令牌,适合分布式和移动端。三者各有优劣,适用于不同场景。
366 0
Cookie、Session、Token、JWT 是什么?万字图解带你一次搞懂!看完这篇,你连老奶奶都能教
|
6月前
|
存储 算法 安全
JWT深度解析:现代Web身份验证的通行证为什么现在都是JWT为什么要restful-优雅草卓伊凡
JWT深度解析:现代Web身份验证的通行证为什么现在都是JWT为什么要restful-优雅草卓伊凡
351 41
JWT深度解析:现代Web身份验证的通行证为什么现在都是JWT为什么要restful-优雅草卓伊凡
|
8月前
|
机器学习/深度学习 人工智能 文字识别
从“泛读”到“精读”:合合信息文档解析如何让大模型更懂复杂文档?
随着deepseek等大模型逐渐步入视野,理论上文档解析工作应能大幅简化。 然而,实际情况却不尽如人意。当前的多模态大模型虽然具备强大的视觉与语言交互能力,但在解析非结构化文档时,仍面临复杂版式、多元素混排以及严密逻辑推理等挑战。
308 0
|
10月前
|
Serverless 对象存储 人工智能
智能文件解析:体验阿里云多模态信息提取解决方案
在当今数据驱动的时代,信息的获取和处理效率直接影响着企业决策的速度和质量。然而,面对日益多样化的文件格式(文本、图像、音频、视频),传统的处理方法显然已经无法满足需求。
409 4
智能文件解析:体验阿里云多模态信息提取解决方案
|
10月前
|
文字识别 开发者 数据处理
多模态数据信息提取解决方案评测报告!
阿里云推出的《多模态数据信息提取》解决方案,利用AI技术从文本、图像、音频和视频中提取关键信息,支持多种应用场景,大幅提升数据处理效率。评测涵盖部署体验、文档清晰度、模板简化、示例验证及需求适配性等方面。方案表现出色,部署简单直观,功能强大,适合多种业务场景。建议增加交互提示、多语言支持及优化OCR和音频转写功能...
356 3
多模态数据信息提取解决方案评测报告!
|
10月前
|
数据采集 XML API
深入解析BeautifulSoup:从sohu.com视频页面提取关键信息的实战技巧
深入解析BeautifulSoup:从sohu.com视频页面提取关键信息的实战技巧
|
11月前
|
JSON 自然语言处理 Java
OpenAI API深度解析:参数、Token、计费与多种调用方式
随着人工智能技术的飞速发展,OpenAI API已成为许多开发者和企业的得力助手。本文将深入探讨OpenAI API的参数、Token、计费方式,以及如何通过Rest API(以Postman为例)、Java API调用、工具调用等方式实现与OpenAI的交互,并特别关注调用具有视觉功能的GPT-4o使用本地图片的功能。此外,本文还将介绍JSON模式、可重现输出的seed机制、使用代码统计Token数量、开发控制台循环聊天,以及基于最大Token数量的消息列表限制和会话长度管理的控制台循环聊天。
3696 7
|
自然语言处理 数据可视化 前端开发
从数据提取到管理:合合信息的智能文档处理全方位解析【合合信息智能文档处理百宝箱】
合合信息的智能文档处理“百宝箱”涵盖文档解析、向量化模型、测评工具等,解决了复杂文档解析、大模型问答幻觉、文档解析效果评估、知识库搭建、多语言文档翻译等问题。通过可视化解析工具 TextIn ParseX、向量化模型 acge-embedding 和文档解析测评工具 markdown_tester,百宝箱提升了文档处理的效率和精确度,适用于多种文档格式和语言环境,助力企业实现高效的信息管理和业务支持。
从数据提取到管理:合合信息的智能文档处理全方位解析【合合信息智能文档处理百宝箱】
|
机器学习/深度学习 自然语言处理 JavaScript
信息论、机器学习的核心概念:熵、KL散度、JS散度和Renyi散度的深度解析及应用
在信息论、机器学习和统计学领域中,KL散度(Kullback-Leibler散度)是量化概率分布差异的关键概念。本文深入探讨了KL散度及其相关概念,包括Jensen-Shannon散度和Renyi散度。KL散度用于衡量两个概率分布之间的差异,而Jensen-Shannon散度则提供了一种对称的度量方式。Renyi散度通过可调参数α,提供了更灵活的散度度量。这些概念不仅在理论研究中至关重要,在实际应用中也广泛用于数据压缩、变分自编码器、强化学习等领域。通过分析电子商务中的数据漂移实例,展示了这些散度指标在捕捉数据分布变化方面的独特优势,为企业提供了数据驱动的决策支持。
1487 2
信息论、机器学习的核心概念:熵、KL散度、JS散度和Renyi散度的深度解析及应用
|
JSON 安全 Go
Go语言中使用JWT鉴权、Token刷新完整示例,拿去直接用!
本文介绍了如何在 Go 语言中使用 Gin 框架实现 JWT 用户认证和安全保护。JWT(JSON Web Token)是一种轻量、高效的认证与授权解决方案,特别适合微服务架构。文章详细讲解了 JWT 的基本概念、结构以及如何在 Gin 中生成、解析和刷新 JWT。通过示例代码,展示了如何在实际项目中应用 JWT,确保用户身份验证和数据安全。完整代码可在 GitHub 仓库中查看。
2147 1

推荐镜像

更多
  • DNS
  • 下一篇
    oss云网关配置