You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Quarkus中自定义JWT解析?处理sub非字符串类型问题

问题

使用SmallRye JWT作为Quarkus应用的授权工具,仅负责验证JWT令牌(不生成)。当前遇到的问题是:传入的令牌中sub声明为数值类型(如45),但SmallRye JWT解析器要求该声明必须是java.lang.String类型,导致验证失败。无法修改令牌生成方,需要在Quarkus应用端做适配。

报错信息

Caused by: org.jose4j.jwt.consumer.InvalidJwtException: JWT (claims->{"iss":"...","iat":...,"exp":...,"nbf":...,"jti":"...","sub":45,"prv":"...","pid": ...}) rejected due to invalid claims or other invalid content. Additional details: [[18] The value of the 'sub' claim is not the expected type (1517 - Cannot cast java.lang.Long to java.lang.String)]

当前配置(application.properties)

smallrye.jwt.verify.key-format=JWK
smallrye.jwt.verify.key.location=JWTSecret.jwk
smallrye.jwt.verify.algorithm=HS256

解决方案

方法1:自定义JWT Claim映射器

通过实现ClaimMapper接口,手动拦截并转换sub声明的类型:

  1. 创建自定义映射器类:
import io.smallrye.jwt.auth.principal.ClaimMapper;
import io.smallrye.jwt.auth.principal.JWTCallerPrincipal;
import io.smallrye.jwt.auth.principal.ParseException;
import jakarta.enterprise.context.ApplicationScoped;
import java.util.Map;

@ApplicationScoped
public class CustomSubClaimMapper implements ClaimMapper {
    @Override
    public void mapClaims(Map<String, Object> claims, JWTCallerPrincipal principal) throws ParseException {
        Object subValue = claims.get("sub");
        // 若sub为非字符串类型,转换为字符串后存回
        if (subValue != null && !(subValue instanceof String)) {
            claims.put("sub", String.valueOf(subValue));
        }
    }
}
  1. 在配置文件中指定使用该映射器:
smallrye.jwt.claim-mapper=com.yourpackage.CustomSubClaimMapper

方法2:调整JwtConsumer验证规则

通过扩展JwtConsumerBuilderCustomizer,修改JWT消费者的验证逻辑,允许sub为数值类型并完成转换:

  1. 创建自定义消费者配置类:
import io.smallrye.jwt.build.JwtConsumerBuilderCustomizer;
import jakarta.enterprise.context.ApplicationScoped;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
import org.jose4j.jwt.consumer.JwtContext;

@ApplicationScoped
public class CustomJwtConsumerCustomizer implements JwtConsumerBuilderCustomizer {
    @Override
    public void customize(JwtConsumerBuilder builder) {
        builder.setCustomValidator(context -> {
            JwtContext jwtContext = (JwtContext) context;
            Object sub = jwtContext.getJwtClaims().getClaimValue("sub");
            if (sub != null) {
                // 将数值类型的sub转为字符串并存回
                jwtContext.getJwtClaims().setClaim("sub", String.valueOf(sub));
            }
            return null; // 返回null表示验证通过
        });
    }
}

验证

完成配置后重启Quarkus应用,测试传入带有数值类型sub的JWT令牌,此时解析器应能正常完成验证流程。


内容的提问来源于stack exchange,提问作者E. Dn

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 09:30:49