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

重启Spring资源服务器遇Signed JWT rejected错误的解决咨询

解决Spring资源服务器重启时JWT验证错误:"Signed JWT rejected: Another algorithm expected, or no matching key(s) found"

重启Spring资源服务器时触发如下错误:

"Signed JWT rejected: Another algorithm expected, or no matching key(s) found"

该错误来自DefaultJwtProcessor,核心触发代码片段:

JWTClaimsSet claimsSet = extractJWTClaimsSet(signedJWT);

List<? extends Key> keyCandidates = selectKeys(signedJWT.getHeader(), claimsSet, context);

if (keyCandidates == null || keyCandidates.isEmpty()) {
    throw new BadJOSEException("Signed JWT rejected: Another algorithm expected, or no matching key(s) found");
}

以下是我按照Spring授权服务器示例实现的配置代码:

授权服务器配置代码

@Bean
@Lazy
public JWKSource<SecurityContext> jwkSource() {
    final RSAKey rsaKey = generateRsa();
    final JWKSet jwkSet = new JWKSet(rsaKey);

    return new ImmutableJWKSet<>(jwkSet);
}

public static RSAKey generateRsa() {
        final KeyPair keyPair = generateRsaKey();
        final RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        final RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        // @formatter:off
        return new RSAKey.Builder(publicKey)
            .privateKey(privateKey)
            .keyID(UUID.randomUUID().toString())
            .build();
        // @formatter:on
    }

static KeyPair generateRsaKey() {
    KeyPair keyPair;

    try {
        final KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance("RSA");

        keyPairGenerator.initialize(2048);
        keyPair = keyPairGenerator.generateKeyPair();
    } catch (Exception ex) {
        throw new IllegalStateException(ex);
    }
    return keyPair;
}

资源服务器配置代码

private JwtDecoder jwtDecoder(final String issuerUri) {
    return NimbusJwtDecoder.withIssuerLocation(issuerUri).jwsAlgorithm(SignatureAlgorithm.RS256).build();
}

问题排查与解决方法

1. 显式指定JWT签名算法

当前授权服务器生成RSA密钥时未明确指定签名算法,可能导致签发JWT时使用的算法与资源服务器配置的RS256不匹配。修改generateRsa()方法,显式添加算法配置:

return new RSAKey.Builder(publicKey)
    .privateKey(privateKey)
    .keyID(UUID.randomUUID().toString())
    .algorithm(JWSAlgorithm.RS256) // 明确指定RS256算法
    .build();

2. 持久化RSA密钥对

你的授权服务器每次启动都会生成新的RSA密钥对,导致重启前签发的JWT用旧密钥签名,重启后资源服务器获取新公钥无法验证旧JWT。解决方式是将密钥对持久化:

  • 提前生成RSA密钥对,将公钥、私钥以PEM格式保存到配置文件或数据库
  • 修改generateRsaKey()方法,从持久化存储加载固定密钥,而非每次生成新密钥:
static KeyPair loadRsaKey() {
    try {
        // 从配置读取PEM格式的公钥和私钥内容
        String publicKeyPem = "你的公钥PEM内容";
        String privateKeyPem = "你的私钥PEM内容";
        
        // 解析公钥
        String cleanPublicKey = publicKeyPem.replaceAll("-----BEGIN PUBLIC KEY-----", "")
                                            .replaceAll("-----END PUBLIC KEY-----", "")
                                            .trim();
        RSAPublicKey publicKey = (RSAPublicKey) KeyFactory.getInstance("RSA")
            .generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(cleanPublicKey)));
        
        // 解析私钥
        String cleanPrivateKey = privateKeyPem.replaceAll("-----BEGIN PRIVATE KEY-----", "")
                                              .replaceAll("-----END PRIVATE KEY-----", "")
                                              .trim();
        RSAPrivateKey privateKey = (RSAPrivateKey) KeyFactory.getInstance("RSA")
            .generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(cleanPrivateKey)));
        
        return new KeyPair(publicKey, privateKey);
    } catch (Exception ex) {
        throw new IllegalStateException(ex);
    }
}

然后将generateRsa()中的generateRsaKey()替换为loadRsaKey()。

3. 验证JWKS端点返回内容

访问授权服务器的.well-known/jwks.json端点,确认返回的JWK包含:

  • alg字段值为RS256
  • kid字段与JWT头中的kid一致
    确保资源服务器能正确获取到该端点的公钥信息。

4. 调整JwtDecoder构建方式

若上述步骤无效,尝试直接指定JWKS端点构建JwtDecoder:

private JwtDecoder jwtDecoder(final String jwksUri) {
    // jwksUri示例:http://你的授权服务器地址/oauth2/jwks
    return NimbusJwtDecoder.withJwkSetUri(jwksUri).jwsAlgorithm(SignatureAlgorithm.RS256).build();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 23:30:28