在Java HTTP连接中将客户端证书设置为请求属性?

我有一个Java应用程序通过带有SSL的套接字连接到另一个Java应用程序,因此我的客户端JVM已经设置了-Djavax.net.ssl.keyStore-Djavax.net.ssl.trustStore属性。

此应用程序需要向需要客户端身份validation的Web服务器发出一些HTTP请求。 我可以使用Java中的URLConnection打开连接,返回HTTPSURLConnectionImpl

我想在请求中向Web服务器提供的客户端证书与设置为我的JVM系统属性的客户端证书不同。 有没有办法设置客户端证书。 作为HTTPSURLConnectionImpl的请求属性?

直接通过HTTPSURLConnectionImpl的请求属性设置SSL“客户端证书”是不够的,因为还需要数字签名来certificate您拥有证书。 SSL已经自动完成所有这些操作,因此使用该层是有意义的。

您有两种方法可以解决您的问题。

通过配置

您可以将客户端密钥和证书添加到JVM KeyStore,当服务器请求您的客户端SSL身份validation时,应该在运行时将其选中。 (SSL / TLS就是为此而设计的:服务器将要求由其受信任的权限签署的客户端证书,这允许SSL引擎选择正确的证书,即使您的KeyStore包含许多证书也是如此)。

通过代码

您可以使用自定义的KeyStore / TrustStore来滚动自己的SSLContext 。 这有点复杂(我不会详细说明如何在Java中构建Keystore实例),但它的要点在于:

 public static void main(String[] args) throws Exception { KeyStore clientKeyStore = ... // Whatever KeyStore clientTrustStore = ... // Whatever you need to load // We build the KeyManager (SSL client credentials we can send) KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyFactory.init(clientKeyStore, "password".toCharArray()); KeyManager[] km = keyFactory.getKeyManagers(); // We build the TrustManager (Server certificates we trust) TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustFactory.init(clientTrustStore); TrustManager[] tm = trustFactory.getTrustManagers(); // We build a SSLContext with both our trust/key managers SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(km, tm, null); SSLSocketFactory sslSf = sslContext.getSocketFactory(); // We prepare a URLConnection URL url = new URL("https://www.google.com"); URLConnection urlConnection = url.openConnection(); // Before actually opening the sockets, we affect the SSLSocketFactory HttpsURLConnection httpsUrlConnection = (HttpsURLConnection) urlConnection; httpsUrlConnection.setSSLSocketFactory(sslSf); // Ready to go ! }