我正在建立与一台我无法控制的远程服务器的HTTPS连接。该服务器具有由受信任的CA生成的SSL证书,但在其SSL握手中未包含中间证书。
例如。 受信任的CA证书-> 中间证书(未提供)->服务器证书(已提供)
通常,服务器会提供服务器证书和中间证书。如果没有中间证书,则我的HTTP客户端无法识别SSL证书,从而导致SSL连接失败。
我正在尝试使用Apache HTTP客户端4.5进行连接。
例如。 受信任的CA证书-> 中间证书(未提供)->服务器证书(已提供)
通常,服务器会提供服务器证书和中间证书。如果没有中间证书,则我的HTTP客户端无法识别SSL证书,从而导致SSL连接失败。
我正在尝试使用Apache HTTP客户端4.5进行连接。
val httpClientBuilder = HttpClientBuilder.create()
.useSystemProperties()
如果我下载证书并将其设置在密钥库中再将其附加到连接上,那么我就可以让事情正常运行:
Security.addProvider(new BouncyCastleProvider())
val certPem = new PEMParser(new PemReader(new FileReader("trust-chain.crt")))
val certHolder = certPem.readObject().asInstanceOf[X509CertificateHolder]
val cert = new JcaX509CertificateConverter()
.setProvider("BC")
.getCertificate(certHolder)
val keyStore = KeyStore.getInstance(KeyStore.getDefaultType)
keyStore.load(null)
keyStore.setCertificateEntry("cert-alias", cert)
val sslContextBuilder = SSLContextBuilder.create()
.loadKeyMaterial(keyStore, "changeit".toCharArray)
.loadTrustMaterial(keyStore, null)
val httpClientBuilder = HttpClientBuilder.create()
.useSystemProperties()
.setSSLContext(sslContextBuilder.build())
但是这个方法在证书过期后就会失效。我也可以启用信任自签名证书,但这会带来相当大的安全隐患,我不想走这条路:
val sslContextBuilder = SSLContextBuilder.create()
.loadKeyMaterial(keyStore, "changeit".toCharArray)
.loadTrustMaterial(keyStore, new TrustSelfSignedStrategy)
有没有办法设置 Apache HTTP Client (或另一个JVM HTTPS / SSL库),使其在服务器未提供中间证书的情况下自动下载这些证书(类似于大多数 Web 浏览器)?