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

Setting a client certificate as a request property in a Java HTTP connection?

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

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

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

中的请求 属性

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

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

通过配置

您可以将客户端密钥和证书添加到您的 JVM KeyStore,当服务器要求您的客户端 SSL 身份验证时,应该会在运行时获取它。 (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 !
}