Spring Boot 3.2.4验证jwt.io通过的JWT时出现无效签名错误
问题:Spring Boot 3.2.4验证JWT返回无效签名错误
操作步骤
1. 生成RSA密钥
# 创建私钥 openssl genrsa -out jwtRSA256-private.pem 2048 # 从私钥中提取公钥 openssl rsa -in jwtRSA256-private.pem -pubout -outform PEM -out src/main/resources/jwtRSA256-public.pem
2. 生成JWT的脚本
# 运行此脚本前需确保已创建公钥和私钥 # 运行方式: # ./generate-rsa-token > token encode() { input=$1 echo -n ${input} | base64 | sed s/\+/-/ | sed -E s/=+$// } header=$(encode '{"alg":"RS256","typ":"JWT"}') payload=$(encode '{ "sub": "john", "scope": [ "role1", "role2", "GUEST" ] }') signature=$(echo -n "${header}.${payload}." \ | openssl dgst -sha256 -binary -sign jwtRSA256-private.pem \ | openssl enc -base64 \ | tr -d '\n=' \ | tr -- '+/' '-_') echo -n ${header}.${payload}.${signature}
3. Spring Boot安全配置
@Configuration @EnableWebSecurity @EnableMethodSecurity @RequiredArgsConstructor public class SecurityConfig { private final AppJwtProperties appJwtProperties; @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { return http .csrf(AbstractHttpConfigurer::disable) .oauth2ResourceServer(configurer -> configurer.jwt(Customizer.withDefaults())) .build(); } @Bean public JwtDecoder jwtDecoder() { return NimbusJwtDecoder.withPublicKey(appJwtProperties.getRsaPublicKey()).build(); } }
4. 应用配置文件
app: jwt: rsa-public-key: jwtRSA256-public.pem
5. 请求结果
调用接口返回401,错误信息:
WWW-Authenticate: Bearer error="invalid_token", error_description="An error occurred while attempting to decode the Jwt: Signed JWT rejected: Invalid signature"
堆栈跟踪:
2024-04-19T08:10:21.138-04:00 TRACE 90136 --- [greetings] [nio-8080-exec-3] o.s.s.oauth2.jwt.NimbusJwtDecoder : Failed to process JWT com.nimbusds.jose.proc.BadJWSException: Signed JWT rejected: Invalid signature at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:378) ~[nimbus-jose-jwt-9.24.4.jar:9.24.4] at com.nimbusds.jwt.proc.DefaultJWTProcessor.process(DefaultJWTProcessor.java:303) ~[nimbus-jose-jwt-9.24.4.jar:9.24.4] at org.springframework.security.oauth2.jwt.NimbusJwtDecoder.createJwt(NimbusJwtDecoder.java:158) ~[spring-security-oauth2-jose-6.2.3.jar:6.2.3] at org.springframework.security.oauth2.jwt.NimbusJwtDecoder.decode(NimbusJwtDecoder.java:138) ~[spring-security-oauth2-jose-6.2.3.jar:6.2.3]
问题原因
生成JWT的脚本中,签名计算时多了一个多余的点:
signature=$(echo -n "${header}.${payload}." \
这里的${header}.${payload}.末尾多了一个点,正确的JWT签名应该是对header.payload(两个部分用点分隔,无末尾点)进行哈希签名。这个多余的点导致签名内容和标准JWT要求的不一致,所以Spring Boot的Nimbus解码器验证失败。
你提供的验证链接里的token是正确生成的(无多余点的签名内容),但实际curl请求中使用的token是用有问题的脚本生成的,因此出现验证不通过的情况。
修复方案
修改生成签名的命令,去掉末尾的点:
signature=$(echo -n "${header}.${payload}" \ | openssl dgst -sha256 -binary -sign jwtRSA256-private.pem \ | openssl enc -base64 \ | tr -d '\n=' \ | tr -- '+/' '-_')
重新生成JWT后,再进行请求即可通过验证。
内容的提问来源于stack exchange,提问作者JJFraney
相关产品推荐
相关产品推荐

