JJWT (Java)Java
错误信息
Invalid compact JWT string: Compact JWSs must contain exactly 2 period characters, and compact JWEs must contain exactly 4. Found: 0
也可能输出为
- io.jsonwebtoken.MalformedJwtException: Invalid compact JWT string: Compact JWSs must contain exactly 2 period characters, and compact JWEs must contain exactly 4. Found: 1
- io.jsonwebtoken.MalformedJwtException: Compact JWT strings may not contain whitespace.
- io.jsonwebtoken.MalformedJwtException: JWT strings must contain exactly 2 period characters. Found: 0
这是 JJWT 0.12+ 的措辞(注意“Found”前面有两个空格)。JJWT 0.11 及更早版本的措辞是“JWT strings must contain exactly 2 period characters. Found: N”。包含空格的输入会更早失败,报出“Compact JWT strings may not contain whitespace.”。
JJWT (Java) — io.jsonwebtoken.MalformedJwtException from JwtParser.parse*
含义
JJWT 统计了输入中的点号,数量既不是签名令牌(JWS)的 2 个,也不是加密令牌(JWE)的 4 个。这个字符串不是紧凑格式的 JWT,因此没有检查任何密钥或签名。“Found: 0”通常表示这是一个不透明的值,例如会话 ID 或 API 密钥;如果报错提到空白字符,说明值上还带着 `Bearer` 前缀或换行符。
原因
这个值不是 JWT
常见不透明的 OAuth 令牌、会话 cookie、API 密钥、`"null"` 或空的请求头值。只有由点号分隔的 base64url 段组成的字符串才是紧凑格式的 JWT。
传入了完整的 Authorization 请求头
常见`Bearer eyJ…` 中含有空格,JJWT 在统计点号之前就会拒绝它。先去掉认证方案前缀。
令牌缺少一部分
偶见在点号处被截断的令牌(日志截断、有长度限制的数据库列、手动复制)只剩一个点号(“Found: 1”)。
修复方法
- 1.
正确地从请求头中提取令牌
只接受 `Bearer <token>`(方案名不区分大小写),其他一律返回 401。
java static String bearerToken(String authorizationHeader) { if (authorizationHeader == null) return null; String[] parts = authorizationHeader.trim().split("\\s+", 2); if (parts.length != 2 || !parts[0].equalsIgnoreCase("Bearer")) return null; return parts[1]; } - 2.
或者交给框架来提取
Spring Security 的资源服务器支持会提取并校验 Bearer 令牌,包括按 RFC 6750 返回错误响应。
java // Spring Security resource server: the BearerTokenAuthenticationFilter extracts the token for you. @Bean SecurityFilterChain api(HttpSecurity http) throws Exception { return http .authorizeHttpRequests(auth -> auth.anyRequest().authenticated()) .oauth2ResourceServer(oauth -> oauth.jwt(Customizer.withDefaults())) .build(); }