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

Spring Boot 2迁移至3后RsaSignatureValidator初始化失败排查

问题描述

将Web服务从Spring Boot 2迁移到3后,DefaultSignatureValidatorFactory尝试创建RsaSignatureValidator对象时抛出NoClassDefFoundError。jar包中存在RsaSignatureValidator类,IntelliJ也能正常跳转查看代码,且相同代码在Spring Boot 2环境下运行正常。报错发生在代码进入构造函数之前,具体错误为:

java.lang.NoClassDefFoundError: Could not initialize class io.jsonwebtoken.impl.crypto.RsaSignatureValidator

首次触发静态初始化失败的堆栈跟踪如下:

java.lang.NoSuchFieldError: id_TA_ECDSA_SHA_1
    at org.bouncycastle.jce.provider.asymmetric.ECMappings.<init>(Unknown Source)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    at java.base/java.lang.reflect.ReflectAccess.newInstance(ReflectAccess.java:128)
    at java.base/jdk.internal.reflect.ReflectionFactory.newInstance(ReflectionFactory.java:347)
    at java.base/java.lang.Class.newInstance(Class.java:645)
    at org.bouncycastle.jce.provider.BouncyCastleProvider.loadAlgorithms(Unknown Source)
    at org.bouncycastle.jce.provider.BouncyCastleProvider.setup(Unknown Source)
    at org.bouncycastle.jce.provider.BouncyCastleProvider.access$000(Unknown Source)
    at org.bouncycastle.jce.provider.BouncyCastleProvider$1.run(Unknown Source)
    at java.base/java.security.AccessController.doPrivileged(AccessController.java:318)
    at org.bouncycastle.jce.provider.BouncyCastleProvider.<init>(Unknown Source)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    at java.base/java.lang.reflect.ReflectAccess.newInstance(ReflectAccess.java:128)
    at java.base/jdk.internal.reflect.ReflectionFactory.newInstance(ReflectionFactory.java:347)
    at java.base/java.lang.Class.newInstance(Class.java:645)
    at io.jsonwebtoken.lang.Classes.newInstance(Classes.java:156)
    at io.jsonwebtoken.lang.RuntimeEnvironment.enableBouncyCastleIfPossible(RuntimeEnvironment.java:53)
    at io.jsonwebtoken.lang.RuntimeEnvironment.<clinit>(RuntimeEnvironment.java:62)
    at io.jsonwebtoken.impl.crypto.RsaProvider.<clinit>(RsaProvider.java:59)
    at io.jsonwebtoken.impl.crypto.DefaultSignatureValidatorFactory.createSignatureValidator(DefaultSignatureValidatorFactory.java:43)
    at io.jsonwebtoken.impl.crypto.DefaultJwtSignatureValidator.<init>(DefaultJwtSignatureValidator.java:50)
    at io.jsonwebtoken.impl.crypto.DefaultJwtSignatureValidator.<init>(DefaultJwtSignatureValidator.java:39)
    at io.jsonwebtoken.impl.DefaultJwtParser.createSignatureValidator(DefaultJwtParser.java:541)
    at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:402)
    at io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:550)
    at io.jsonwebtoken.impl.ImmutableJwtParser.parse(ImmutableJwtParser.java:153)
    at com.okta.jwt.impl.jjwt.TokenVerifierSupport.decode(TokenVerifierSupport.java:81)
    at com.okta.jwt.impl.jjwt.JjwtAccessTokenVerifier.decode(JjwtAccessTokenVerifier.java:56)
    at io.onq.service.security.AuthTokenUtil.getClaimsFromOktaToken(AuthTokenUtil.java:108)
    at io.onq.service.security.AuthTokenUtil.getFromAuthProviderToken(AuthTokenUtil.java:125)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752)
    at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:49)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752)
    at org.springframework.aop.framework.adapter.MethodBeforeAdviceInterceptor.invoke(MethodBeforeAdviceInterceptor.java:58)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752)
    at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:97)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:752)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703)
    at io.onq.service.security.AuthTokenUtil$$SpringCGLIB$$0.getFromAuthProviderToken(<generated>)
    at io.onq.web.filter.UserAuthenticationTokenFilter.doFilterInternal(UserAuthenticationTokenFilter.java:61)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at org.springframework.security.web.header.HeaderWriterFilter.doHeadersAfter(HeaderWriterFilter.java:90)
    at org.springframework.security.web.header.HeaderWriterFilter.doFilterInternal(HeaderWriterFilter.java:75)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:82)
    at org.springframework.security.web.context.SecurityContextHolderFilter.doFilter(SecurityContextHolderFilter.java:69)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter.doFilterInternal(WebAsyncManagerIntegrationFilter.java:62)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at org.springframework.security.web.session.DisableEncodeUrlFilter.doFilterInternal(DisableEncodeUrlFilter.java:42)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:374)
    at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:233)
    at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:191)
    at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:351)
    at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:267)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:116)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:185)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:158)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:177)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:97)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:542)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:119)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:78)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:357)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:400)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:859)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1734)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191)
    at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.base/java.lang.Thread.run(Thread.java:833)
排查与解决步骤

从堆栈跟踪可以看出,真正的根因是java.lang.NoSuchFieldError: id_TA_ECDSA_SHA_1,这个错误发生在BouncyCastle的ECMappings类初始化阶段,进而导致RsaSignatureValidator类的静态初始化失败,最终抛出NoClassDefFoundError。按以下步骤排查:

  • 检查BouncyCastle依赖版本冲突
    执行mvn dependency:tree(Maven)或./gradlew dependencies(Gradle),输出所有org.bouncycastle相关依赖,确认是否存在多版本共存的情况(比如旧版bcprov-jdk15on和新版bcprov-jdk18on同时引入)。

  • 统一BouncyCastle依赖版本
    Spring Boot 3的依赖管理默认适配较新的BouncyCastle版本,直接使用Spring Boot提供的版本即可;若项目有自定义依赖,需指定与Spring Boot 3兼容的版本(如1.77及以上),并排除冲突的旧版本依赖。

  • 验证JDK与BouncyCastle版本适配性
    Spring Boot 3要求JDK 17+,BouncyCastle的不同版本对应不同JDK版本:bcprov-jdk17on适配JDK 17,bcprov-jdk18on适配JDK 18+,需确保依赖版本与当前使用的JDK匹配。

  • 排除Spring Boot自动引入的冲突依赖
    如果Spring Boot starter自动引入了不兼容的BouncyCastle版本,在依赖配置中排除冲突模块。例如Maven配置:

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-security</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.bouncycastle</groupId>
                <artifactId>bcprov-jdk15on</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    
  • 升级JJWT版本至兼容Spring Boot 3的版本
    项目中使用的JJWT(io.jsonwebtoken)需升级到0.11.x及以上版本,旧版JJWT可能与Spring Boot 3、新版BouncyCastle或JDK 17+存在兼容性问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 11:42:35