为服务器身份验证设置客户端后出现 okhttp 客户端错误

问题描述

我们正在尝试使用使用 okhttp 客户端的 minio-java 客户端将对象上传到存储桶。目前我们使用的服务器只支持服务器认证,不支持双向 tls,这主要意味着我们必须验证服务器提供的证书和给定的 CA 证书。 出于这个原因,我们确实创建了以下方法来简单地在trustedstore 中传递ca 证书文件

private OkHttpClient addCertificates(OkHttpClient httpClient,Path certificatesDir) throws CertificateException,KeyStoreException,NoSuchAlgorithmException,IOException,UnrecoverableKeyException,KeyManagementException
{
    // Todo: remove printing of certificates
    String certContents = Files.readString(certificatesDir);
    log.debug("certificate contents: {}",certContents);
    
    Collection<? extends Certificate> certificates = null;
    try (FileInputStream fis = new FileInputStream(certificatesDir.toFile().getAbsolutePath()))
    {
        certificates = CertificateFactory.getInstance("X.509").generateCertificates(fis);
    }

    if (certificates == null || certificates.isEmpty())
    {
        throw new IllegalArgumentException("expected non-empty set of trusted certificates");
    }

    char[] password = "password".tochararray();

    KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
    keyStore.load(null,password);

    int index = 0;
    for (Certificate certificate : certificates)
    {
        String certificatealias = Integer.toString(index++);
        keyStore.setCertificateEntry(certificatealias,certificate);
    }
    
    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    trustManagerFactory.init(keyStore);
    TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();
    
    SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
    sslContext.init(null,trustManagers,null);
    SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

    return httpClient.newBuilder().sslSocketFactory(sslSocketFactory,(x509trustmanager) trustManagers[0]).build();
}

如果能帮助我们了解 minio 如何将 ca/client 证书与 MinioClient.java 中的“enableExternalCertificates”分开,这需要一个单一的 SSL 证书文件

private OkHttpClient enableExternalCertificates(OkHttpClient httpClient,String filename)
    throws GeneralSecurityException,IOException {
  Collection<? extends Certificate> certificates = null;
  try (FileInputStream fis = new FileInputStream(filename)) {
    certificates = CertificateFactory.getInstance("X.509").generateCertificates(fis);
  }

  if (certificates == null || certificates.isEmpty()) {
    throw new IllegalArgumentException("expected non-empty set of trusted certificates");
  }

  char[] password = "password".tochararray(); // Any password will work.

  // Put the certificates a key store.
  KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
  // By convention,'null' creates an empty key store.
  keyStore.load(null,password);

  int index = 0;
  for (Certificate certificate : certificates) {
    String certificatealias = Integer.toString(index++);
    keyStore.setCertificateEntry(certificatealias,certificate);
  }

  // Use it to build an X509 trust manager.
  KeyManagerFactory keyManagerFactory =
      KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
  keyManagerFactory.init(keyStore,password);
  TrustManagerFactory trustManagerFactory =
      TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
  trustManagerFactory.init(keyStore);

  final KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();
  final TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();

  SSLContext sslContext = SSLContext.getInstance("TLS");
  sslContext.init(keyManagers,null);
  SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

  return httpClient
      .newBuilder()
      .sslSocketFactory(sslSocketFactory,(x509trustmanager) trustManagers[0])
      .build();
}

目前,我们确实有以下例外情况,我不确定它们是否与证书有关。

---连接异常---

java.net.ConnectException: 无法连接到对象存储/10.10.10.10:9000 at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.java:248) at okhttp3.internal.connection.RealConnection.connect( RealConnection.java:166) 在 okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257) 在 okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135) 在 okhttp3.internal.connection.StreamAllocation.newStream (StreamAllocation.java:114) at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) at okhttp3.internal.http.RealInterceptorChain。继续(RealInterceptorChain.java:121) at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) at okhttp3.internal.http.RealInterceptorChain .继续(真实我nterceptorChain.java:121) at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) at okhttp3.internal.http.RetryAnd.FollowUpIntercept (RetryAndFollowUpInterceptor.java:126) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147) at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121) at okhttp3.InterceptorChain.java:121) at okhttp3.InterceptorChain.proceed(RealInterceptorChain.java:147) java:254) at okhttp3.RealCall.execute(RealCall.java:92) at io.minio.MinioClient.execute(MinioClient.java:635) at io.minio.MinioClient.getRegion(MinioClient.java:805) at io。 minio.MinioClient.execute(MinioClient.java:568) at io.minio.MinioClient.executeHead(MinioClient.java:837) at io.minio.MinioClient.bucketExists(MinioClient.java:2209) at com.ericsson.sc.s3c .S3MinioClientHandler.bucketExists(S3MinioClientHandler.java:201) 在 com.ericsson.sc.s3c.S3Agent.checkBucket(S3Agent. java:80) 在 com.ericsson.sc.s3c.S3Agent.lambda$uploadFiletoBucket$3(S3Agent.java:57) 在 java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) ) 在 java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) 在 java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655) 在 java.base/ java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) 在 java.base/java.util.stream.AbstractPipeline.wrapAndcopyInto(AbstractPipeline.java:474) 在 java.base/java.util.stream.ForEachOps$ ForEachOp.evaluateSequential(ForEachOps.java:150) 在 java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) 在 java.base/java.util.stream.AbstractPipeline.evaluate( AbstractPipeline.java:234) at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497) at com.ericsson.sc.s3c.S3Agent.lambda$uploadFiletoBucket$4(S3Agent.java:51) at io.reactivex.internal.operators.completable。 CompletableFromAction.subscribeActual(CompletableFromAction.java:35) at io.reactivex.Completable.subscribe(Completable.java:2309) at io.reactivex.internal.operators.mixed.FlowableConcatMapCompletable$ConcatMapCompletableObserver.drain(FlowableConcatMap533) at io: .reactivex.internal.operators.mixed.FlowableConcatMapCompletable$ConcatMapCompletableObserver.onNext(FlowableConcatMapCompletable.java:118) 在 io.reactivex.internal.operators.flowable.FlowableDoOnEach$DoOnEachSubscriber.onNext(FlowableDoOnEach.java:92) .operators.flowable.FlowableOnBackpressureLatest$BackpressureLatestSubscriber.drain(FlowableOnBackpressureLatest.java:129) 在 io.reactivex.internal.operators.flowable.FlowableOnBackpressureLatest$BackpressureLatestSubscriber.onNext(FlowableOnBackpressureLatest.java:68) 在 io.reactivex.inableternal .FlowableThrottleLatest$ThrottleLatestSubscriber.drain(FlowableThrottleLatest.java:221) 在 io.reactivex.internal.operators.flowable .FlowableThrottleLatest$ThrottleLatestSubscriber.onNext(FlowableThrottleLatest.java:119) 在 io.reactivex.internal.operators.flowable.FlowableDoOnEach$DoOnEachSubscriber.onNext(FlowableDoOnEach.java:92) 在 io.reactivex.internal.util.NotificationLite(NotificationLite) .java:224) 在 io.reactivex.internal.operators.flowable.FlowableReplay$BoundedReplayBuffer.replay(FlowableReplay.java:855) 在 io.reactivex.internal.operators.flowable.FlowableReplay$ReplaySubscriber.onNext(FlowableReplay.java:388) ) 在 io.reactivex.internal.operators.flowable.FlowableDoOnEach$DoOnEachSubscriber.onNext(FlowableDoOnEach.java:92) 在 io.reactivex.internal.operators.flowable.FlowableDoOnEach$DoOnEachSubscriber.onNext(FlowableDoOnEach.java:92) 在 io. io.reactivex.internal.operators.flowable.FlowableFlatMapSingle$FlatMapSingleSubscriber.innerSuccess(FlowableFlatMapSingle.java:175) at io.reactivex.internal.operators.flowable.FlowableFlatMapSingle$FlatMapSingleSubscriber$InnerObserver.onSuccess(Flowable.jFlatMapSingle) ava:364) 在 io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.onSuccess(SingleSubscribeOn.java:68) 在 io.reactivex.internal.operators.single.SingleFromCallable.subscribeActual(SingleFromCallable.java:56) 在 io .reactivex.Single.subscribe(Single.java:3603) 在 io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89) 在 io.reactivex.Scheduler$disposeTask.run(Scheduler.java :578) 在 io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66) 在 io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57) 在 java.base/java.util。 concurrent.FutureTask.run(FutureTask.java:264) 在 java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) 在 java.base/java.util.concurrent.ThreadPoolExecutor.runWorker( ThreadPoolExecutor.java:1128) 在 java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java :628) 在 java.base/java.lang.Thread.run(Thread.java:834) 引起:java.net.ConnectException:在 java.base/java.net.PlainSocketImpl 的连接超时(连接超时)。 socketConnect(Native Method) at java.base/java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:399) at java.base/java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:242) at java.base/java。 net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:224) 在 java.base/java.net.socksSocketImpl.connect(SocksSocketImpl.java:392) 在 java.base/java.net.socket.connect(Socket.java:609)在 okhttp3.internal.platform.Platform.connectSocket(Platform.java:129) 在 okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.java:246) ...省略了 64 个常用帧

--- 套接字异常---

java.net.socketException:连接重置在 java.base/java.net.socketInputStream.read(SocketInputStream.java:186) at java.base/java.net.socketInputStream.read(SocketInputStream.java:140) at okio.Okio$2.read(Okio.java:140) at okio.AsyncTimeout$2.read(AsyncTimeout.java:237) at okio.RealBufferedSource.read(RealBufferedSource.java:47) at okhttp3.internal.http1.Http1Codec$AbstractSource .read(Http1Codec.java:363) at okhttp3.internal.http1.Http1Codec$UnkNownLengthSource.read(Http1Codec.java:507) at okio.Buffer.writeall(Buffer.java:1135) at okio.RealBufferedSource.readString(RealBufferedSource. java:199) at okhttp3.ResponseBody.string(ResponseBody.java:176) at io.minio.MinioClient.execute(MinioClient.java:663) at io.minio.MinioClient.getRegion(MinioClient.java:805) at io。 minio.MinioClient.putObject(MinioClient.java:4584) at io.minio.MinioClient.putObject(MinioClient.java:2726) at io.minio.MinioClient.uploadobject(MinioClient.java:2890) at com.ericsson.sc.s3c .S3MinioClientHandler.uploadFile (S3MinioClientHandler.java:237) 在 com.ericsson.sc.s3c.S3Agent.lambda$uploadFiletoBucket$3(S3Agent.java:60) 在 java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps. java:183) 在 java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177) 在 java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1655) 在 java .base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484) 在 java.base/java.util.stream.AbstractPipeline.wrapAndcopyInto(AbstractPipeline.java:474) 在 java.base/java.util.stream .ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150) 在 java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173) 在 java.base/java.util.stream.AbstractPipeline .evaluate(AbstractPipeline.java:234) 在 java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497) 在 com.ericsson.sc.s3c.S3Agent.lambda$uploadFiletoBucket$4(S3Agent.java: 51) 在 io.reactivex.internal .operators.completable.CompletableFromAction.subscribeActual(CompletableFromAction.java:35) 在 io.reactivex.Completable.subscribe(Completable.java:2309) 在 io.reactivex.internal.operators.mixed.FlowableConcatMapCompletable$ConcatMapCompletableObserver.java:35) :253) 在 io.reactivex.internal.operators.mixed.FlowableConcatMapCompletable$ConcatMapCompletableObserver.onNext(FlowableConcatMapCompletable.java:118) 在 io.reactivex.internal.operators.flowable.FlowableDoOnEach$DoOnEachSubscriber.onNext) atach2EachSubscriber.onNext(FlowableConcatMapCompletable.java:118) io.reactivex.internal.operators.flowable.FlowableOnBackpressureLatest$BackpressureLatestSubscriber.drain(FlowableOnBackpressureLatest.java:129) at io.reactivex.internal.operators.flowable.FlowableOnBackpressureLatest$BackpressureLatestSubscriber.onNext(FlowableOnBackpressureLatest.java:68) internal.operators.flowable.FlowableThrottleLatest$ThrottleLatestSubscriber.drain(FlowableThrottleLatest.java:221) 在 io.reactivex.inte rnal.operators.flowable.FlowableThrottleLatest$ThrottleLatestSubscriber.onNext(FlowableThrottleLatest.java:119) at io.reactivex.internal.operators.flowable.FlowableDoOnEach$DoOnEachSubscriber.onNext(FlowableDoOnEach.java:92) atternal.reactivex.in NotificationLite.accept(NotificationLite.java:224) at io.reactivex.internal.operators.flowable.FlowableReplay$BoundedReplayBuffer.replay(FlowableReplay.java:855) at io.reactivex.internal.operators.flowable.FlowableReplay$ReplaySubscriber.onNext( FlowableReplay.java:388) 在 io.reactivex.internal.operators.flowable.FlowableDoOnEach$DoOnEachSubscriber.onNext(FlowableDoOnEach.java:92) 在 io.reactivex.internal.operators.flowable.FlowableDoOnEach$DoOnEachSubscriber.onNext(FlowableDoOnEach) 92) 在 io.reactivex.internal.operators.flowable.FlowableFlatMapSingle$FlatMapSingleSubscriber.innerSuccess(FlowableFlatMapSingle.java:175) 在 io.reactivex.internal.operators.flowable.FlowableFlatMapSingle$FlatMapSingleSubscriber$InnerObserver. FlowableFlatMapSingle.java:364) 在 io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.onSuccess(SingleSubscribeOn.java:68) 在 io.reactivex.internal.operators.single.SingleFromCallable.subscribeActual(SingleFrom6Callable.java)在 io.reactivex.Single.subscribe(Single.java:3603) 在 io.reactivex.internal.operators.single.SingleSubscribeOn$SubscribeOnObserver.run(SingleSubscribeOn.java:89) 在 io.reactivex.Scheduler$disposeTask.run(Scheduler) .java:578) 在 io.reactivex.internal.schedulers.ScheduledRunnable.run(ScheduledRunnable.java:66) 在 io.reactivex.internal.schedulers.ScheduledRunnable.call(ScheduledRunnable.java:57) 在 java.base/java。 util.concurrent.FutureTask.run(FutureTask.java:264) 在 java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) 在 java.base/java.util.concurrent.ThreadPoolExecutor。 runWorker(ThreadPoolExecutor.java:1128) 在 java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run( ThreadPoolExecutor.java:628) 在 java.base/java.lang.Thread.run(Thread.java:834)

我认为检查存储桶是否存在后的第一个异常可能与端点主机名“对象存储”的解析有关,但我们仍然有 ip 地址,并且所有其他请求(如存储桶创建)都有“连接重置” " 异常可能是由于第一个异常,因为我们仍然使用相同的客户端。但是,我们确实注意到新客户端有时会直接生成“连接重置”异常。

根据minio,使用的文件名对应环境变量SSL_CERT_FILE,对应TLS证书文件(例如自签名TLS证书)的路径。此外,如果我们不生成我们自己的自定义 http 客户端,MinioClient.Builder.build() 将创建认的 HTTP 客户端对象,并使用上面的 enableExternalCertificates() 加载此类 TLS 证书。至于http客户端,我觉得这个论坛最合适。

任何建议将不胜感激。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...