【发布时间】:2021-06-25 16:20:01
【问题描述】:
请阅读底部的“更新”。控制器的名称似乎有问题。根据名称,不应用 SSL 配置。
我的 spring 应用程序的UserService 连接到在开发中使用自签名证书的外部服务器。我将自签名且有效的证书添加到 java 密钥库 ./dev-truststore.jks 并使用此 @Configuration:
@Profile("development")
@Configuration
class SSLConfigDev {
@Suppress("unused")
@PostConstruct
private fun configureSSL() {
System.setProperty("javax.net.ssl.trustStore", "./dev-truststore.jks")
System.setProperty("javax.net.ssl.trustStorePassword", "secret")
}
}
这是减少的UserServiceImpl,仍然显示错误:
import org.keycloak.admin.client.Keycloak
// ...
@Service
class UserServiceFeatureImpl(
private val userRepository: UserRepository,
private val kc: Keycloak,
) : UserService {
override suspend fun createUser(email: String, pw: String) {
try {
val realmResources = kc.realm("myRealm")
val usersResource = realmResources.users()
// The next line works fine until I define the new TaskService as
// described below. Then it fails with the SSL exception shown below.
val existingUsers = usersResource.search(email, 0, 1)
// ...
} catch (e: Exception) {
throw CreateAccountException("Could not create account", e)
}
}
}
这是创建用户的途径:
@RestController
class UserController(
private val userService: UserService,
) {
@PostMapping("/users/new")
@ResponseStatus(HttpStatus.CREATED)
suspend fun create(@RequestBody @Valid dto: CredentialsDTO) {
userService.createUser(dto.email, dto.password)
}
}
这是 Keycloak 的 bean 创建:
@Configuration
@ConfigurationProperties("keycloak")
class KeycloakConfig{
lateinit var serverUrl: String
lateinit var realm: String
lateinit var clientId: String
lateinit var clientSecret: String
lateinit var frontEndClientId: String
@Bean
fun init(): Keycloak {
return KeycloakBuilder.builder()
.serverUrl(serverUrl)
.grantType(OAuth2Constants.CLIENT_CREDENTIALS)
.realm(realm)
.clientId(clientId)
.clientSecret(clientSecret)
.resteasyClient(
ResteasyClientBuilder().connectionPoolSize(10).build()
)
.build()
}
}
这很好用。
现在,我正在开发一个新的不相关功能(控制器/服务/存储库),突然 create-user 路由停止工作,因为它无法再连接到 keycloak 服务,因为它无法执行 SSL 握手。请注意,create-user 操作与新服务/功能中的任何内容都无关,也没有被修改。
javax.ws.rs.ProcessingException: RESTEASY004655: Unable to invoke request: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
完整的堆栈跟踪是:
2021-06-25 18:04:19.050 ERROR 7821 --- [or-http-epoll-3] a.w.r.e.AbstractErrorWebExceptionHandler : [755b0875-1] 500 Server Error for HTTP POST "/users/new"
com.example.backend.user.CreateAccountException: Could not create account
at com.example.backend.user.UserServiceFeatureImpl.createUser$suspendImpl(UserServiceFeatureImpl.kt:278) ~[main/:na]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ Handler com.example.backend.user.UserController#create(CredentialsDTO, Continuation) [DispatcherHandler]
|_ checkpoint ⇢ com.example.backend.core.ReactorContextLocaleWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.authorization.AuthorizationWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.authorization.ExceptionTranslationWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.authentication.logout.LogoutWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.savedrequest.ServerRequestCacheWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.context.SecurityContextServerWebExchangeWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.authentication.AuthenticationWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.context.ReactorContextWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.header.HttpHeaderWriterWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.config.web.server.ServerHttpSecurity$ServerWebExchangeReactorContextWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.security.web.server.WebFilterChainProxy [DefaultWebFilterChain]
|_ checkpoint ⇢ org.springframework.boot.actuate.metrics.web.reactive.server.MetricsWebFilter [DefaultWebFilterChain]
|_ checkpoint ⇢ HTTP POST "/users/new" [ExceptionHandlingWebHandler]
Stack trace:
at com.example.backend.user.UserServiceFeatureImpl.createUser$suspendImpl(UserServiceFeatureImpl.kt:278) ~[main/:na]
at com.example.backend.user.UserServiceFeatureImpl.createUser(UserServiceFeatureImpl.kt) ~[main/:na]
at com.example.backend.user.UserServiceFeatureImpl$$FastClassBySpringCGLIB$$ed9e17ac.invoke(<generated>) ~[main/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.7.jar:5.3.7]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.3.7.jar:5.3.7]
at com.example.backend.user.UserServiceFeatureImpl$$EnhancerBySpringCGLIB$$2ccf6d25.createUser(<generated>) ~[main/:na]
at com.example.backend.user.UserServicePermissionsImpl.createUser$suspendImpl(UserServicePermissionsImpl.kt:47) ~[main/:na]
at com.example.backend.user.UserServicePermissionsImpl.createUser(UserServicePermissionsImpl.kt) ~[main/:na]
at com.example.backend.user.UserServicePermissionsImpl$$FastClassBySpringCGLIB$$d7f96f3a.invoke(<generated>) ~[main/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.7.jar:5.3.7]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.3.7.jar:5.3.7]
at com.example.backend.user.UserServicePermissionsImpl$$EnhancerBySpringCGLIB$$fb5d3241.createUser(<generated>) ~[main/:na]
at com.example.backend.user.UserController.create$suspendImpl(UserController.kt:116) ~[main/:na]
at com.example.backend.user.UserController.create(UserController.kt) ~[main/:na]
at com.example.backend.user.UserController$$FastClassBySpringCGLIB$$d1552207.invoke(<generated>) ~[main/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.7.jar:5.3.7]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.3.7.jar:5.3.7]
at com.example.backend.user.UserController$$EnhancerBySpringCGLIB$$f0dbf2c8.create(<generated>) ~[main/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at kotlin.reflect.jvm.internal.calls.CallerImpl$Method.callMethod(CallerImpl.kt:97) ~[kotlin-reflect-1.5.0.jar:1.5.0-release-749 (1.5.0)]
at kotlin.reflect.jvm.internal.calls.CallerImpl$Method$Instance.call(CallerImpl.kt:113) ~[kotlin-reflect-1.5.0.jar:1.5.0-release-749 (1.5.0)]
at kotlin.reflect.jvm.internal.KCallableImpl.call(KCallableImpl.kt:108) ~[kotlin-reflect-1.5.0.jar:1.5.0-release-749 (1.5.0)]
at kotlin.reflect.full.KCallables.callSuspend(KCallables.kt:55) ~[kotlin-reflect-1.5.0.jar:1.5.0-release-749 (1.5.0)]
at org.springframework.core.CoroutinesUtils$invokeSuspendingFunction$mono$1.invokeSuspend(CoroutinesUtils.kt:64) ~[spring-core-5.3.7.jar:5.3.7]
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) ~[kotlin-stdlib-1.5.0.jar:1.5.0-release-749 (1.5.0)]
at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:377) ~[kotlinx-coroutines-core-jvm-1.5.0.jar:na]
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30) ~[kotlinx-coroutines-core-jvm-1.5.0.jar:na]
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25) ~[kotlinx-coroutines-core-jvm-1.5.0.jar:na]
at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110) ~[kotlinx-coroutines-core-jvm-1.5.0.jar:na]
at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126) ~[kotlinx-coroutines-core-jvm-1.5.0.jar:na]
at kotlinx.coroutines.reactor.MonoKt.monoInternal$lambda-2(Mono.kt:90) ~[kotlinx-coroutines-reactor-1.5.0.jar:na]
at reactor.core.publisher.MonoCreate.subscribe(MonoCreate.java:57) ~[reactor-core-3.4.6.jar:3.4.6]
// ...
at reactor.netty.channel.FluxReceive.terminateReceiver(FluxReceive.java:469) ~[reactor-netty-core-1.0.7.jar:1.0.7]
at reactor.netty.channel.FluxReceive.drainReceiver(FluxReceive.java:261) ~[reactor-netty-core-1.0.7.jar:1.0.7]
at reactor.netty.channel.FluxReceive.request(FluxReceive.java:130) ~[reactor-netty-core-1.0.7.jar:1.0.7]
at reactor.core.publisher.FluxMap$MapSubscriber.request(FluxMap.java:162) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxPeek$PeekSubscriber.request(FluxPeek.java:137) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxMap$MapSubscriber.request(FluxMap.java:162) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.MonoCollect$CollectSubscriber.onSubscribe(MonoCollect.java:103) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxMap$MapSubscriber.onSubscribe(FluxMap.java:92) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxPeek$PeekSubscriber.onSubscribe(FluxPeek.java:170) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.core.publisher.FluxMap$MapSubscriber.onSubscribe(FluxMap.java:92) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.netty.channel.FluxReceive.startReceiver(FluxReceive.java:168) ~[reactor-netty-core-1.0.7.jar:1.0.7]
at reactor.netty.channel.FluxReceive.lambda$subscribe$2(FluxReceive.java:147) ~[reactor-netty-core-1.0.7.jar:1.0.7]
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:384) ~[netty-transport-native-epoll-4.1.65.Final-linux-x86_64.jar:4.1.65.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na]
Caused by: javax.ws.rs.ProcessingException: RESTEASY004655: Unable to invoke request: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:328) ~[resteasy-client-3.13.2.Final.jar:3.13.2.Final]
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:443) ~[resteasy-client-3.13.2.Final.jar:3.13.2.Final]
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:149) ~[resteasy-client-3.13.2.Final.jar:3.13.2.Final]
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:112) ~[resteasy-client-3.13.2.Final.jar:3.13.2.Final]
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76) ~[resteasy-client-3.13.2.Final.jar:3.13.2.Final]
at com.sun.proxy.$Proxy131.grantToken(Unknown Source) ~[na:na]
at org.keycloak.admin.client.token.TokenManager.grantToken(TokenManager.java:90) ~[keycloak-admin-client-13.0.1.jar:13.0.1]
at org.keycloak.admin.client.token.TokenManager.getAccessToken(TokenManager.java:70) ~[keycloak-admin-client-13.0.1.jar:13.0.1]
at org.keycloak.admin.client.token.TokenManager.getAccessTokenString(TokenManager.java:65) ~[keycloak-admin-client-13.0.1.jar:13.0.1]
at org.keycloak.admin.client.resource.BearerAuthFilter.filter(BearerAuthFilter.java:52) ~[keycloak-admin-client-13.0.1.jar:13.0.1]
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.filterRequest(ClientInvocation.java:579) ~[resteasy-client-3.13.2.Final.jar:3.13.2.Final]
at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:440) ~[resteasy-client-3.13.2.Final.jar:3.13.2.Final]
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invokeSync(ClientInvoker.java:149) ~[resteasy-client-3.13.2.Final.jar:3.13.2.Final]
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientInvoker.invoke(ClientInvoker.java:112) ~[resteasy-client-3.13.2.Final.jar:3.13.2.Final]
at org.jboss.resteasy.client.jaxrs.internal.proxy.ClientProxy.invoke(ClientProxy.java:76) ~[resteasy-client-3.13.2.Final.jar:3.13.2.Final]
at com.sun.proxy.$Proxy173.search(Unknown Source) ~[na:na]
at com.example.backend.user.UserServiceFeatureImpl.createUser$suspendImpl(UserServiceFeatureImpl.kt:247) ~[main/:na]
at com.example.backend.user.UserServiceFeatureImpl.createUser(UserServiceFeatureImpl.kt) ~[main/:na]
at com.example.backend.user.UserServiceFeatureImpl$$FastClassBySpringCGLIB$$ed9e17ac.invoke(<generated>) ~[main/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.7.jar:5.3.7]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.3.7.jar:5.3.7]
at com.example.backend.user.UserServiceFeatureImpl$$EnhancerBySpringCGLIB$$2ccf6d25.createUser(<generated>) ~[main/:na]
at com.example.backend.user.UserServicePermissionsImpl.createUser$suspendImpl(UserServicePermissionsImpl.kt:47) ~[main/:na]
at com.example.backend.user.UserServicePermissionsImpl.createUser(UserServicePermissionsImpl.kt) ~[main/:na]
at com.example.backend.user.UserServicePermissionsImpl$$FastClassBySpringCGLIB$$d7f96f3a.invoke(<generated>) ~[main/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.7.jar:5.3.7]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.3.7.jar:5.3.7]
at com.example.backend.user.UserServicePermissionsImpl$$EnhancerBySpringCGLIB$$fb5d3241.createUser(<generated>) ~[main/:na]
at com.example.backend.user.UserController.create$suspendImpl(UserController.kt:116) ~[main/:na]
at com.example.backend.user.UserController.create(UserController.kt) ~[main/:na]
at com.example.backend.user.UserController$$FastClassBySpringCGLIB$$d1552207.invoke(<generated>) ~[main/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) ~[spring-core-5.3.7.jar:5.3.7]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688) ~[spring-aop-5.3.7.jar:5.3.7]
at com.example.backend.user.UserController$$EnhancerBySpringCGLIB$$f0dbf2c8.create(<generated>) ~[main/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
at kotlin.reflect.jvm.internal.calls.CallerImpl$Method.callMethod(CallerImpl.kt:97) ~[kotlin-reflect-1.5.0.jar:1.5.0-release-749 (1.5.0)]
at kotlin.reflect.jvm.internal.calls.CallerImpl$Method$Instance.call(CallerImpl.kt:113) ~[kotlin-reflect-1.5.0.jar:1.5.0-release-749 (1.5.0)]
at kotlin.reflect.jvm.internal.KCallableImpl.call(KCallableImpl.kt:108) ~[kotlin-reflect-1.5.0.jar:1.5.0-release-749 (1.5.0)]
at kotlin.reflect.full.KCallables.callSuspend(KCallables.kt:55) ~[kotlin-reflect-1.5.0.jar:1.5.0-release-749 (1.5.0)]
at org.springframework.core.CoroutinesUtils$invokeSuspendingFunction$mono$1.invokeSuspend(CoroutinesUtils.kt:64) ~[spring-core-5.3.7.jar:5.3.7]
at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) ~[kotlin-stdlib-1.5.0.jar:1.5.0-release-749 (1.5.0)]
at kotlinx.coroutines.internal.DispatchedContinuationKt.resumeCancellableWith(DispatchedContinuation.kt:377) ~[kotlinx-coroutines-core-jvm-1.5.0.jar:na]
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable(Cancellable.kt:30) ~[kotlinx-coroutines-core-jvm-1.5.0.jar:na]
at kotlinx.coroutines.intrinsics.CancellableKt.startCoroutineCancellable$default(Cancellable.kt:25) ~[kotlinx-coroutines-core-jvm-1.5.0.jar:na]
at kotlinx.coroutines.CoroutineStart.invoke(CoroutineStart.kt:110) ~[kotlinx-coroutines-core-jvm-1.5.0.jar:na]
at kotlinx.coroutines.AbstractCoroutine.start(AbstractCoroutine.kt:126) ~[kotlinx-coroutines-core-jvm-1.5.0.jar:na]
at kotlinx.coroutines.reactor.MonoKt.monoInternal$lambda-2(Mono.kt:90) ~[kotlinx-coroutines-reactor-1.5.0.jar:na]
// ...
at reactor.core.publisher.FluxMap$MapSubscriber.onSubscribe(FluxMap.java:92) ~[reactor-core-3.4.6.jar:3.4.6]
at reactor.netty.channel.FluxReceive.startReceiver(FluxReceive.java:168) ~[reactor-netty-core-1.0.7.jar:1.0.7]
at reactor.netty.channel.FluxReceive.lambda$subscribe$2(FluxReceive.java:147) ~[reactor-netty-core-1.0.7.jar:1.0.7]
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at io.netty.channel.epoll.EpollEventLoop.run(EpollEventLoop.java:384) ~[netty-transport-native-epoll-4.1.65.Final-linux-x86_64.jar:4.1.65.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[netty-common-4.1.65.Final.jar:4.1.65.Final]
at java.base/java.lang.Thread.run(Thread.java:832) ~[na:na]
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:325) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:268) ~[na:na]
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:263) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1340) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.onConsumeCertificate(CertificateMessage.java:1215) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.consume(CertificateMessage.java:1158) ~[na:na]
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396) ~[na:na]
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:445) ~[na:na]
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:423) ~[na:na]
at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:182) ~[na:na]
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:171) ~[na:na]
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1475) ~[na:na]
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1381) ~[na:na]
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:441) ~[na:na]
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:412) ~[na:na]
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.createLayeredSocket(SSLConnectionSocketFactory.java:436) ~[httpclient-4.5.13.jar:4.5.13]
at org.apache.http.conn.ssl.SSLConnectionSocketFactory.connectSocket(SSLConnectionSocketFactory.java:384) ~[httpclient-4.5.13.jar:4.5.13]
at org.apache.http.impl.conn.DefaultHttpClientConnectionOperator.connect(DefaultHttpClientConnectionOperator.java:142) ~[httpclient-4.5.13.jar:4.5.13]
at org.apache.http.impl.conn.PoolingHttpClientConnectionManager.connect(PoolingHttpClientConnectionManager.java:376) ~[httpclient-4.5.13.jar:4.5.13]
at org.apache.http.impl.execchain.MainClientExec.establishRoute(MainClientExec.java:393) ~[httpclient-4.5.13.jar:4.5.13]
at org.apache.http.impl.execchain.MainClientExec.execute(MainClientExec.java:236) ~[httpclient-4.5.13.jar:4.5.13]
at org.apache.http.impl.execchain.ProtocolExec.execute(ProtocolExec.java:186) ~[httpclient-4.5.13.jar:4.5.13]
at org.apache.http.impl.execchain.RetryExec.execute(RetryExec.java:89) ~[httpclient-4.5.13.jar:4.5.13]
at org.apache.http.impl.execchain.RedirectExec.execute(RedirectExec.java:110) ~[httpclient-4.5.13.jar:4.5.13]
at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:185) ~[httpclient-4.5.13.jar:4.5.13]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83) ~[httpclient-4.5.13.jar:4.5.13]
at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56) ~[httpclient-4.5.13.jar:4.5.13]
at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:323) ~[resteasy-client-3.13.2.Final.jar:3.13.2.Final]
... 98 common frames omitted
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439) ~[na:na]
at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306) ~[na:na]
at java.base/sun.security.validator.Validator.validate(Validator.java:264) ~[na:na]
at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231) ~[na:na]
at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132) ~[na:na]
at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1324) ~[na:na]
... 122 common frames omitted
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) ~[na:na]
at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) ~[na:na]
at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297) ~[na:na]
at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434) ~[na:na]
... 127 common frames omitted
2021-06-25 18:04:19.072 INFO 7821 --- [or-http-epoll-3] reactor.netty.http.server.AccessLog : 127.0.0.1:59138 - - [25/Jun/2021:18:04:18 +0200] "POST /users/new HTTP/1.1" 500 23140 306 ms
我通过从新服务中删除所有方法来跟踪问题(因此它是一个空接口 + @Service 注释类中的实现):
interface TaskService {}
和
@Service
class TaskServiceImpl(
// next line implies the error.
private val userService: UserService,
) : TaskService {}
当我从 TaskServiceImpl 中删除 private val userService: UserService 依赖项时,userService 能够连接到 keycloak 并且 create-user 路由不会失败,但如果我再次添加它,上述 SSL 握手创建用户路由发生错误。
也依赖于UserService 的其他服务并不意味着同样的错误。新服务完全是空的,所以我很困惑为什么其他服务没有暗示同样的错误?
例如,该服务也使用UserService,它确实不暗示用户创建路线失败:
@Service
class FeedServiceImpl(
private val userService: UserService,
// other dependencies
) : FeedService {
/// ...
}
TaskService 在两个控制器中使用,我已删除所有路由和所有其他依赖项:
@RestController
class TaskReviewController(
// adding or removing this dependency does not change anything
private val taskService: TaskService,
) {
}
@RestController
class ActionsController(
// adding or removing this dependency implies the error
private val taskService: TaskService,
) {
}
当我从两者中删除taskService 依赖项时,错误不会发生。当我只将它添加到ActionsController 时,错误确实会发生 - 但如果我只将它添加到TaskReviewController,那么错误确实不会发生。
我不知道如何进一步追踪它。我认为这可能表示一个依赖循环,但没有循环,因为UserService 不依赖于任何新的TaskService,并且在添加新的TaskService 时没有被修改。而且UserService 也不依赖于任何控制器。
有什么想法吗?
--
- spring-boot 2.5.0
- org.keycloak:keycloak-admin-client:13.0.1
PS:我还验证了configureSSL 仍在执行,并且我正在运行正确的development 配置文件。
更新
我发现错误取决于控制器的包和名称。如果使用TaskService 的所有控制器在SSLConfigDev 配置之后按字母顺序排列,则不会发生错误:
因此,与“SSLConfigDev”在同一个包中的这个控制器意味着错误:
@RestController
class SSLConfigDeuController(
private val taskService: TaskReviewService,
) {
}
但这很好:
@RestController
class SSLConfigDewController(
private val taskService: TaskReviewService,
) {
}
【问题讨论】:
-
可能您的 UserService 依赖于使用默认 SSL 上下文的 HTTP 客户端(Spring RestTemplate 或 Apache HttpClient)。您应该配置两个具有单独 SSL 上下文的 http 客户端,并将非 SSL http 客户端注入 UserService
-
是的,它使用 RestEasy 客户端连接到 keycloak,但为什么在那之前会起作用?为什么其他服务
@AutowireUserService不会出现这个问题?已经有大约 20 种其他服务。 -
您是否尝试添加
-Djavax.net.debug=all以获得详细信息?你可以添加相关的依赖项来提问吗?您的新服务是使用 HTTPClient 而不是 RESTEasy 吗? -
@user7294900 新的服务接口和它的实现是完全空的,所以它没有使用任何http客户端。
UserService接口及其实现相当复杂。我将添加它的最小版本,稍后当我有更多时间时仍然会显示错误。但是我仍然很困惑,为什么当其他服务将UserService添加为依赖项时不会出现此问题,并想到可能由新服务的名称和类路径上的排序引起的依赖项问题...... ? -
听起来像循环依赖,你有特定方面的代码吗?
标签: spring spring-boot kotlin