使用http客户端-如何获取Java以自动下载中间SSL证书

问题描述:

我正在建立与我无法控制的远程服务器的HTTPS连接.该服务器具有由受信任的CA生成的SSL证书,但在SSL握手中不包括中间证书.

I'm setting up a HTTPS connection to a remote server that I have no control over. The server has an SSL certificate that is generated by a trusted CA but doesn't include the intermediate certificates in their SSL handshake.

例如. 受信任的CA证书->中间证书(未提供)->服务器证书(已提供)

Eg. trusted CA cert -> intermediate cert (not provided) -> server cert (provided)

通常,服务器将提供服务器证书和中间证书.没有中间证书,我的HTTP客户端无法识别SSL证书,并且SSL连接失败.

Typically a server would provide the server cert and intermediate certs. Without the intermediate cert my HTTP client doesn't recognize the SSL cert and the SSL connection fails.

我正在尝试使用Apache HTTP客户端4.5进行连接:

I'm trying to connect using Apache HTTP client 4.5:

  val httpClientBuilder = HttpClientBuilder.create()
    .useSystemProperties()

如果我下载证书,将它们设置在密钥库中并将其附加到连接,则可以使事情正常工作

I can get things working if I download the certificates, set them up in a keystore and attach it to the connection:

  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())

但是,一旦证书过期,这种情况就将中断.我还可以启用信任自签名证书,但这对安全性有很大影响,我不想这样做:

But this is going to break as soon as the certificates expire. I could also enable trusting self signed certificates but that has pretty big security implications and I don't want to go that way:

  val sslContextBuilder = SSLContextBuilder.create()
    .loadKeyMaterial(keyStore, "changeit".toCharArray)
    .loadTrustMaterial(keyStore, new TrustSelfSignedStrategy)

如果服务器不提供中间证书,是否有任何方法可以设置Apache HTTP客户端(或另一个JVM HTTPS/SSL库)以自动下载中间证书?

Is there any way to set up Apache HTTP Client (or another JVM HTTPS/SSL library) to automatically download the intermediate certificates if the server does not provide them (similar to most web browsers)?

我发现使用Oracle JRE,您可以使用Java系统属性-Dcom.sun.security.enableAIAcaIssuers=true

Using the Oracle JRE you can enable automatic downloading of intermediate certificates with the Java system property -Dcom.sun.security.enableAIAcaIssuers=true

要使其正常工作,服务器的证书必须向中间证书(证书的颁发者)提供URI.

For this to work the server's certificate must provide the URI to the intermediate certificate (the certificate's issuer).