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

使用Spring OAuth2资源服务器和对称密钥如何避免KeyLengthException

Spring Security OAuth2资源服务器短HS512密钥签名校验问题解决

问题背景

正在开发基于Spring Boot的资源服务器,需要使用Spring Security OAuth2 Resource Server库的能力。当前遇到的核心限制是:授权服务器为另一款Spring Boot应用,使用早年设置且无法修改的短对称密钥对JWT做HS512签名。

初始配置与密钥长度错误

参照Spring Security官方文档的初始配置如下:

@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests(authorize -> authorize
                        .anyRequest().permitAll())
                .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
    }
    
    @Bean
    public JwtDecoder jwtDecoder(@Value("${jwt.secret-key}") String secretKey) {
        return NimbusJwtDecoder
                .withSecretKey(new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HS512"))
                .macAlgorithm(MacAlgorithm.HS512)
                .build();
    }
}

运行后抛出密钥长度不足的异常:

Caused by: com.nimbusds.jose.KeyLengthException: The secret length must be at least 256 bits
at com.nimbusds.jose.crypto.impl.MACProvider.<init>(MACProvider.java:118) ~[nimbus-jose-jwt-9.10.1.jar:9.10.1]
... 61 common frames omitted

抛出异常的MACProvider不支持自定义配置,无法直接放宽密钥长度要求。

首次修复尝试与签名校验错误

尝试对密钥做补0处理满足长度要求,配置如下:

@Bean
public JwtDecoder jwtDecoder(@Value("${jwt.secret-key}") String secretKey) {
    var key = secretKey.getBytes(StandardCharsets.UTF_8);
    var paddedKey = Arrays.copyOf(key, 128);
    return NimbusJwtDecoder
            .withSecretKey(new SecretKeySpec(paddedKey, "HS512"))
            .macAlgorithm(MacAlgorithm.HS512)
            .build();
}

修改后抛出签名无效异常:

com.nimbusds.jose.proc.BadJWSException: Signed JWT rejected: Invalid signature
... 省略异常栈

根因确认

通过排查授权服务器的JWT生成逻辑,确认其使用io.jsonwebtoken 0.9.1版本库实现签名,生成代码如下:

private String generateToken(Map<String, Object> claims, String username) {
    Header header = Jwts.header();
    header.setType("JWT");
    String jti = UUID.randomUUID().toString();
    Date now = new Date(System.currentTimeMillis());
    return Jwts.builder()
            .setClaims(claims)
            .setHeader((Map<String, Object>) header)
            .setSubject(username)
            .setIssuedAt(now)
            .setIssuer("issuer")
            .setId(jti)
            .signWith(SignatureAlgorithm.HS512, secret)
            .compact();
}

旧版本jjwt库的signWith方法接收字符串类型密钥时,会默认先对字符串做BASE64解码,再将解码后的字节数组作为实际签名密钥。而资源服务器初始直接将密钥字符串转为UTF-8字节数组,导致两端使用的实际密钥不一致,签名校验失败。

最终解决方案

调整密钥处理逻辑,先对配置的密钥字符串做BASE64解码,再对不足长度的密钥做补位处理,最终配置如下:

@Bean
public JwtDecoder jwtDecoder(@Value("${jwt.secret-key}") String secretKey) {
    var key = TextCodec.BASE64.decode(secretKey);
    var paddedKey = key.length < 128 ? Arrays.copyOf(key, 128) : key;
    return NimbusJwtDecoder
            .withSecretKey(new SecretKeySpec(paddedKey, "HS512"))
            .macAlgorithm(MacAlgorithm.HS512)
            .build();
}

内容的提问来源于stack exchange,提问作者Andrea Damiani</think_never_used_51bce0c785ca2f68081bfa7d91973934># Spring Security OAuth2资源服务器短HS512密钥签名校验问题解决

问题背景

正在开发基于Spring Boot的资源服务器,需要使用Spring Security OAuth2 Resource Server库的能力。当前遇到的核心限制是:授权服务器为另一款Spring Boot应用,使用早年设置且无法修改的短对称密钥对JWT做HS512签名。

初始配置与密钥长度错误

参照Spring Security官方文档的初始配置如下:

@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests(authorize -> authorize
                        .anyRequest().permitAll())
                .oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
    }
    
    @Bean
    public JwtDecoder jwtDecoder(@Value("${jwt.secret-key}") String secretKey) {
        return NimbusJwtDecoder
                .withSecretKey(new SecretKeySpec(secretKey.getBytes(StandardCharsets.UTF_8), "HS512"))
                .macAlgorithm(MacAlgorithm.HS512)
                .build();
    }
}

运行后抛出密钥长度不足的异常:

Caused by: com.nimbusds.jose.KeyLengthException: The secret length must be at least 256 bits
at com.nimbusds.jose.crypto.impl.MACProvider.<init>(MACProvider.java:118) ~[nimbus-jose-jwt-9.10.1.jar:9.10.1]
... 61 common frames omitted

抛出异常的MACProvider不支持自定义配置,无法直接放宽密钥长度要求。

首次修复尝试与签名校验错误

尝试对密钥做补0处理满足长度要求,配置如下:

@Bean
public JwtDecoder jwtDecoder(@Value("${jwt.secret-key}") String secretKey) {
    var key = secretKey.getBytes(StandardCharsets.UTF_8);
    var paddedKey = Arrays.copyOf(key, 128);
    return NimbusJwtDecoder
            .withSecretKey(new SecretKeySpec(paddedKey, "HS512"))
            .macAlgorithm(MacAlgorithm.HS512)
            .build();
}

修改后抛出签名无效异常:

com.nimbusds.jose.proc.BadJWSException: Signed JWT rejected: Invalid signature
... 省略异常栈

根因确认

通过排查授权服务器的JWT生成逻辑,确认其使用io.jsonwebtoken 0.9.1版本库实现签名,生成代码如下:

private String generateToken(Map<String, Object> claims, String username) {
    Header header = Jwts.header();
    header.setType("JWT");
    String jti = UUID.randomUUID().toString();
    Date now = new Date(System.currentTimeMillis());
    return Jwts.builder()
            .setClaims(claims)
            .setHeader((Map<String, Object>) header)
            .setSubject(username)
            .setIssuedAt(now)
            .setIssuer("issuer")
            .setId(jti)
            .signWith(SignatureAlgorithm.HS512, secret)
            .compact();
}

旧版本jjwt库的signWith方法接收字符串类型密钥时,会默认先对字符串做BASE64解码,再将解码后的字节数组作为实际签名密钥。而资源服务器初始直接将密钥字符串转为UTF-8字节数组,导致两端使用的实际密钥不一致,签名校验失败。

最终解决方案

调整密钥处理逻辑,先对配置的密钥字符串做BASE64解码,再对不足长度的密钥做补位处理,最终配置如下:

@Bean
public JwtDecoder jwtDecoder(@Value("${jwt.secret-key}") String secretKey) {
    var key = TextCodec.BASE64.decode(secretKey);
    var paddedKey = key.length < 128 ? Arrays.copyOf(key, 128) : key;
    return NimbusJwtDecoder
            .withSecretKey(new SecretKeySpec(paddedKey, "HS512"))
            .macAlgorithm(MacAlgorithm.HS512)
            .build();
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 20:36:00