Java出现:JWT strings must contain exactly 2 period characters. Found: 0的常见原因及解决方案

 更新时间:2026年01月09日 10:08:31   作者:hellotutu  
这篇文章主要介绍了JWT令牌解析失败的原因和解决方法,包括Header、Payload和Signature三段式结构,常见错误原因,通用解决方案以及额外注意点,需要的朋友可以参考下

这个错误的核心是:你传入的JWT令牌字符串没有包含必需的2个英文句点(.),导致JWT解析器无法按标准拆分令牌结构

一、先理解JWT的标准结构

合法的JWT令牌必须是 Header.Payload.Signature 三段式结构(包含2个句点),例如:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
  • 第一段:Header(Base64编码)
  • 第二段:Payload(Base64编码)
  • 第三段:Signature(签名)
  • 段与段之间用英文句点 . 分隔

二、错误的常见原因(按优先级排查)

1. 传入的令牌为空/空白字符串

  • 现象:前端未传递token、后端接收时为空,或token被误置为空字符串("")。
  • 排查:
// 解析前先校验token是否为空
String token = request.getHeader("Authorization");
if (token == null || token.trim().isEmpty()) {
    throw new IllegalArgumentException("JWT令牌不能为空");
}
// 若用Bearer Token,需先截取(例如:Bearer <token>)
if (token.startsWith("Bearer ")) {
    token = token.substring(7).trim(); // 去掉"Bearer "前缀
}

2. 令牌被截断/拼接错误

  • 现象:token传递过程中被截断(如URL编码/解码错误、字符长度限制),或拼接时丢失句点。
  • 排查:
    • 打印原始token值,确认是否完整(例如:System.out.println("原始token:" + token));
    • 检查前端传递时是否对token做了不必要的转义(如把 . 转成 %2E 但后端未解码)。

3. 令牌格式错误(非JWT)

  • 现象:传入的不是JWT令牌,而是普通字符串、SessionID、其他格式的token(如只有一段/一段半)。
  • 排查:
    • 确认生成token的代码是否正确(例如:使用JJWT/Java JWT库生成时,是否完整调用了签名步骤);
    • 示例:正确生成JWT(以JJWT为例):
// 正确生成三段式JWT
String jwt = Jwts.builder()
    .setHeaderParam("alg", "HS256")
    .setSubject("user123")
    .signWith(SignatureAlgorithm.HS256, "secretKey")
    .compact(); // compact()会生成标准的Header.Payload.Signature结构

4. 令牌被篡改/手动修改

  • 现象:token被人为删除句点,或传输中被篡改(如空格替换句点)。
  • 排查:校验token的字符组成,确保仅包含Base64URL合法字符(字母、数字、-_.)。

三、通用解决方案(解析前增加校验)

在解析JWT前,先校验token的格式合法性,避免直接抛出异常:

import io.jsonwebtoken.JwtException;
import io.jsonwebtoken.Jwts;

public String parseJwt(String token) {
    // 第一步:校验非空+句点数量
    if (token == null || token.trim().isEmpty()) {
        throw new IllegalArgumentException("JWT令牌不能为空");
    }
    int dotCount = token.length() - token.replace(".", "").length();
    if (dotCount != 2) {
        throw new IllegalArgumentException("JWT令牌格式错误,必须包含2个句点(.),当前数量:" + dotCount);
    }
    
    // 第二步:解析JWT(示例)
    try {
        return Jwts.parser()
            .setSigningKey("secretKey")
            .parseClaimsJws(token)
            .getBody()
            .getSubject();
    } catch (JwtException e) {
        throw new RuntimeException("JWT解析失败:" + e.getMessage());
    }
}

四、额外注意点

  1. Bearer Token前缀:前端传递的token常带 Bearer 前缀(如 Bearer eyJhbGciOiJIUzI1Ni...),需先截取掉前缀再解析;
  2. Base64URL编码:JWT的段使用Base64URL编码(区别于普通Base64),若手动解码需注意替换字符(+-/_,去掉末尾=);
  3. 框架自动解析:若使用Spring Security OAuth2等框架,需确认配置的token提取器是否正确(如从Header/参数中提取)。

快速定位技巧

在解析代码前添加日志,打印原始token值:

System.out.println("待解析的JWT令牌:[" + token + "]");

通过日志可直接判断:

  • 若打印 [] → token为空;
  • 若打印 [eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9] → 只有一段(缺少2个句点);
  • 若打印 [eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkw] → 只有1个句点(缺少1个)。

到此这篇关于Java出现:JWT strings must contain exactly 2 period characters. Found: 0的常见原因及解决方案的文章就介绍到这了,更多相关Java出现:characters. Found: 0内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • spring整合kaptcha验证码的实现

    spring整合kaptcha验证码的实现

    这篇文章主要介绍了spring整合kaptcha验证码的实现,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • ActiveMQ结合Spring收发消息的示例代码

    ActiveMQ结合Spring收发消息的示例代码

    这篇文章主要介绍了ActiveMQ结合Spring收发消息的示例代码,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-10-10
  • JVM自定义类加载器在代码扩展性实践分享

    JVM自定义类加载器在代码扩展性实践分享

    这篇文章主要介绍了JVM自定义类加载器在代码扩展性实践分享,一个类型从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期将会经历加载、验证、准备、解析、初始化 、使用和卸载七个阶段,其中验证、准备、解析三个部分统称为连接
    2022-06-06
  • springboot实现图片大小压缩功能

    springboot实现图片大小压缩功能

    这篇文章主要为大家详细介绍了springboot实现图片大小压缩功能,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-04-04
  • 带你快速搞定java多线程(2)

    带你快速搞定java多线程(2)

    这篇文章主要介绍了java多线程编程实例,分享了几则多线程的实例代码,具有一定参考价值,加深多线程编程的理解还是很有帮助的,需要的朋友可以参考下
    2021-07-07
  • Java实现滑动验证码的示例代码

    Java实现滑动验证码的示例代码

    这篇文章主要为大家介绍了如何用Java语言实现滑动验证码的生成,项目采用了springboot,maven等技术,感兴趣的小伙伴可以跟随小编学习一下
    2022-02-02
  • Java设计模式之装饰模式详解

    Java设计模式之装饰模式详解

    这篇文章主要介绍了Java设计模式中的装饰者模式,装饰者模式即Decorator Pattern,装饰模式是在不必改变原类文件和使用继承的情况下,动态地扩展一个对象的功能,装饰模式又名包装模式。装饰器模式以对客户端透明的方式拓展对象的功能,是继承关系的一种替代方案
    2022-08-08
  • Java多线程编程:线程的原理和使用安全

    Java多线程编程:线程的原理和使用安全

    文章主要介绍了线程的基本概念、线程和进程的区别、线程的创建方法、线程的常见方法与属性、线程的安全问题等,线程是程序执行流的最小单位,可以并发执行并共享数据,线程的生命周期状态包括新建、就绪、运行、阻塞、死亡等
    2026-05-05
  • java自己手动控制kafka的offset操作

    java自己手动控制kafka的offset操作

    这篇文章主要介绍了java自己手动控制kafka的offset操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-02-02
  • 5分钟搞定java单例模式

    5分钟搞定java单例模式

    单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式,本文给大家介绍下java单例模式的相关知识,感兴趣的朋友一起看看吧
    2022-03-03

最新评论