【问题标题】:Mutual TLS using a Retrofit (Retrofit2) Client (Kotlin) within Springboot使用带有 Spring Boot 的 Retrofit (Retrofit2) 客户端 (Kotlin) 的双向 TLS
【发布时间】:2020-05-01 15:15:58
【问题描述】:

我一直在尝试弄清楚在将 Retrofit 客户端用于 API 时如何提供客户端证书。我对证书很有信心,因为它可以在 Python/requests 中使用,但是为 Retrofit 配置它没有结果。目前我有这个:

@Configuration
@ConditionalOnProperty("serviceApi.enabled")
class ServiceApiConfiguration {
  @Bean
  fun serviceApiEndpoint(@Value("\${serviceApi.baseUrl}") serviceApiBaseUrl: String): HttpUrl = HttpUrl.parse(serviceApiBaseUrl) ?: throw BeanCreationException("Invalid URL: $serviceApiBaseUrl")

  @Bean
  fun serviceApi(serviceApiEndpoint: HttpUrl, mapper: ObjectMapper, retrofitClient: OkHttpClient): ServiceApi {
    return Retrofit.Builder()
      .addConverterFactory(JacksonConverterFactory.create(mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)))
      .addCallAdapterFactory(CoroutineCallAdapterFactory())
      .baseUrl(serviceApiEndpoint)
      .client(retrofitClient)
      .build()
      .create(ServiceApi::class.java)
  }
}

证书在密钥库中,但由于出现此错误,它似乎没有使用它:

javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.ssl.Alerts.getSSLException(Alerts.java:198) ~[na:1.8.0_252]
    at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1967) ~[na:1.8.0_252]
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:331) ~[na:1.8.0_252]
    at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:325) ~[na:1.8.0_252]
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1688) ~[na:1.8.0_252]
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:226) ~[na:1.8.0_252]
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1082) ~[na:1.8.0_252]
    at sun.security.ssl.Handshaker.process_record(Handshaker.java:1010) ~[na:1.8.0_252]
    at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1079) ~[na:1.8.0_252]
    at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1388) ~[na:1.8.0_252]
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1416) ~[na:1.8.0_252]
    at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1400) ~[na:1.8.0_252]
    at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:320) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:284) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:169) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) ~[okhttp-3.12.2.jar:na]
    at com.netflix.spinnaker.okhttp.OkHttp3MetricsInterceptor.intercept(OkHttp3MetricsInterceptor.java:42) ~[kork-web-5.2.2.jar:5.2.2]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) ~[okhttp-3.12.2.jar:na]
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:250) ~[okhttp-3.12.2.jar:na]
    at okhttp3.RealCall$AsyncCall.execute(RealCall.java:201) ~[okhttp-3.12.2.jar:na]
    at okhttp3.internal.NamedRunnable.run(NamedRunnable.java:32) ~[okhttp-3.12.2.jar:na]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_252]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_252]
    at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_252]
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 sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:450) ~[na:1.8.0_252]
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:317) ~[na:1.8.0_252]
    at sun.security.validator.Validator.validate(Validator.java:262) ~[na:1.8.0_252]
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:330) ~[na:1.8.0_252]
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:237) ~[na:1.8.0_252]
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132) ~[na:1.8.0_252]
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1670) ~[na:1.8.0_252]
    ... 33 common frames omitted
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) ~[na:1.8.0_252]
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) ~[na:1.8.0_252]
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280) ~[na:1.8.0_252]
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:445) ~[na:1.8.0_252]
    ... 39 common frames omitted

非常感谢任何帮助!

【问题讨论】:

    标签: spring-boot authentication kotlin retrofit2 client-certificates


    【解决方案1】:

    PKIX path building failed 错误表示您的客户端不信任服务器。 API 是否不使用您的 JRE 信任的证书和链?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-01
      • 2016-11-14
      • 1970-01-01
      • 2021-03-15
      • 2011-02-17
      • 2021-07-28
      • 2021-09-11
      • 2018-07-02
      相关资源
      最近更新 更多