You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python Flask生成的JWT Token在Java中解析时签名匹配异常问题

嘿,我之前也踩过跨语言JWT签名验证的坑,结合你给出的代码来看,问题大概率出在这几个地方:

1. JJWT 0.9.0 用错了解析方法

你Java代码里的parseClaimsJwt()是专门用来解析无签名的明文JWT的,但Flask-JWT-Extended生成的是带HS256签名的JWS(JSON Web Signature),用这个方法去解析签名后的Token,必然会导致签名验证失败。

正确的做法是换成parseClaimsJws()方法,修改后的代码如下:

import java.nio.charset.StandardCharsets;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;

// ...

Claims userJWT = Jwts.parser()
    .setSigningKey("this-really-needs-to-be-changed".getBytes(StandardCharsets.UTF_8))
    .parseClaimsJws(token)
    .getBody();

2. 密钥的字符编码不一致

Python的Flask-JWT-Extended在使用HS256签名时,默认会把JWT_SECRET_KEY字符串转换成UTF-8编码的字节数组;但Java中直接调用setSigningKey(String)时,底层会用JVM的默认字符编码(比如Windows环境下可能是GBK)来生成字节数组,这就导致两边的密钥字节完全不一致,签名自然匹配不上。

上面的代码已经解决了这个问题——显式用StandardCharsets.UTF_8来获取密钥的字节数组,保证和Python端的编码一致。如果想要更规范,也可以用SecretKeySpec来构建密钥对象:

import java.nio.charset.StandardCharsets;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import javax.crypto.spec.SecretKeySpec;

// ...

SecretKey secretKey = new SecretKeySpec(
    "this-really-needs-to-be-changed".getBytes(StandardCharsets.UTF_8),
    SignatureAlgorithm.HS256.getJcaName()
);

Claims userJWT = Jwts.parser()
    .setSigningKey(secretKey)
    .parseClaimsJws(token)
    .getBody();

3. 额外注意:Identity的存储方式

虽然这不是签名不匹配的直接原因,但需要提醒你:Flask-JWT-Extended会把你传入的identity字典序列化成JSON字符串,然后放到JWT的sub(subject)字段里。所以在Java解析完成后,你需要把sub字段的字符串反序列化成对应的用户对象,才能拿到firstnameemail这些信息。比如用Jackson来处理:

import com.fasterxml.jackson.databind.ObjectMapper;

// ...

String subJson = userJWT.getSubject();
UserDTO user = new ObjectMapper().readValue(subJson, UserDTO.class);

内容的提问来源于stack exchange,提问作者ghovat

火山引擎 最新活动