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

Quarkus集成SmallRye JWT时HS256签名验证失败排查

Quarkus中HS256 JWT签名验证失败问题排查

问题现象

Quarkus应用不生成JWT令牌,但持有HS256签名用的密钥qwertyuiopasdfghjklzxcvbnm123456,验证请求中的令牌时始终报错:

io.smallrye.jwt.auth.principal.ParseException: SRJWT07000: Failed to verify a token
...
Caused by: org.jose4j.jwt.consumer.InvalidJwtSignatureException: JWT rejected due to invalid signature. Additional details: [[9] Invalid JWS Signature: JsonWebSignature{"typ":"JWT","alg":"HS256"}->eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJPbmxpbmUgSldUIEJ1aWxkZXIiLCJpYXQiOjE2NjczODI2NzIsImV4cCI6MTY5ODkxODY3MiwiYXVkIjoid3d3LmV4YW1wbGUuY29tIiwic3ViIjoianJvY2tldEBleGFtcGxlLmNvbSIsIkdpdmVuTmFtZSI6IkpvaG5ueSIsIlN1cm5hbWUiOiJSb2NrZXQiLCJFbWFpbCI6Impyb2NrZXRAZXhhbXBsZS5jb20iLCJSb2xlIjpbIk1hbmFnZXIiLCJQcm9qZWN0IEFkbWluaXN0cmF0b3IiXX0.5vBHzbTKjLnAkAIYuA3c50nWV--o9jIWV2i0GZI-aw4]

当前配置

application.properties

smallrye.jwt.verify.key-format=JWK
smallrye.jwt.verify.key.location=JWTSecret.jwk
smallrye.jwt.verify.algorithm=HS256
quarkus.native.resources.includes=JWTSecret.jwk

JWTSecret.jwk文件内容

{
    "kty": "oct",
    "k": "qwertyuiopasdfghjklzxcvbnm123456",
    "alg": "HS256"
}

排查情况

  • 已通过jwt.io用上述密钥验证令牌签名,结果正常,推测问题出在JWK文件或配置中
  • 改用RS256算法(PEM公钥/私钥)验证正常,但业务要求必须使用HS256
  • 业务代码在其他算法下工作正常,暂不考虑代码问题,相关代码如下:
package co.ogram.domain

import org.eclipse.microprofile.jwt.JsonWebToken
import javax.annotation.security.RolesAllowed
import javax.enterprise.inject.Default
import javax.inject.Inject
import javax.ws.rs.*
import javax.ws.rs.core.Context
import javax.ws.rs.core.MediaType
import javax.ws.rs.core.SecurityContext

@Path("/secured")
class TokenSecuredResource {
    @Inject
    @field:Default
    var jwt: JsonWebToken? = null

    @GET
    @Path("/roles-allowed")
    @RolesAllowed("Admin")
    @Produces(MediaType.TEXT_PLAIN)
    fun helloRolesAllowed(@Context ctx: SecurityContext): String? {
         return getResponseString(ctx!!)
    }

    private fun getResponseString(ctx: SecurityContext): String {
        val name: String
        name = if (ctx.userPrincipal == null) {
            "anonymous"
        } else if (ctx.userPrincipal.name != jwt!!.name) {
            throw InternalServerErrorException("Principal and JsonWebToken names do not match")
        } else {
            ctx.userPrincipal.name
        }
        val type = jwt!!.getClaim<Int>("type")
        return String.format(
            "hello + %s,"
                    + " isHttps: %s,"
                    + " authScheme: %s,"
                    + " type: %s,"
                    + " hasJWT: %s",
            name, ctx.isSecure, ctx.authenticationScheme, type, hasJwt()
        )
    }

    private fun hasJwt(): Boolean {
        return jwt!!.claimNames != null
    }
}

解决方案

问题出在JWK文件的k字段值——HS256的密钥在JWK中需要是Base64URL编码后的结果,而非明文直接填写。

方案1:修正JWK文件

  1. 将原始密钥qwertyuiopasdfghjklzxcvbnm123456进行Base64URL编码(替换+为-、/为_,去掉末尾=),编码结果为:cXdlcnR5dWlvcGFzZGZnaGprbHp4Y3Zibm0xMjM0NTY
  2. 修改JWTSecret.jwk文件的k字段:
{
    "kty": "oct",
    "k": "cXdlcnR5dWlvcGFzZGZnaGprbHp4Y3Zibm0xMjM0NTY",
    "alg": "HS256"
}
  1. 重启应用后重新验证即可通过。

方案2:直接使用明文密钥(更简单)

放弃JWK格式,直接在配置中指定原始密钥:
修改application.properties:

smallrye.jwt.verify.key-format=raw
smallrye.jwt.verify.key=qwertyuiopasdfghjklzxcvbnm123456
smallrye.jwt.verify.algorithm=HS256

此方式无需JWK文件,直接用原始密钥即可完成验证。


内容的提问来源于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 05:45:47