简体   繁体   English

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

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

I have a Java application that connects to another Java app through a socket with SSL, so my client JVM already has the -Djavax.net.ssl.keyStore and -Djavax.net.ssl.trustStore properties set. 我有一个Java应用程序通过SSL套接字通过一个套接字连接到另一个Java应用程序,因此我的客户端JVM已经设置了-Djavax.net.ssl.keyStore-Djavax.net.ssl.trustStore属性。

This application needs to make some HTTP requests to a web server that requires client authentication. 此应用程序需要向需要客户端身份验证的Web服务器发出一些HTTP请求。 I can open the connection by using a URLConnection in Java which returns an HTTPSURLConnectionImpl . 我可以使用Java中的URLConnection打开连接,该连接返回HTTPSURLConnectionImpl

The client certificate I want to present to the web server in the request is different than the one set as my JVM system property. 我要在请求中提供给Web服务器的客户端证书与设置为我的JVM系统属性的客户端证书不同。 Is there a way I can set a client cert. 有没有一种方法可以设置客户端证书。 as a request property in the HTTPSURLConnectionImpl ? 作为HTTPSURLConnectionImpl的请求属性?

Setting a SSL "client certificate" is not adequate directly through HTTPSURLConnectionImpl 's request properties, because a digital signature is also required to prove you own the certificate. 直接通过HTTPSURLConnectionImpl的请求属性设置SSL“客户端证书”是不够的,因为还需要数字签名来证明您拥有证书。 SSL already does all that automatically, so to makes sense to use that layer. SSL已经自动执行所有操作,因此使用该层很有意义。

You have two ways to solve your issue going forward. 您有两种方法可以解决您的问题。

Through configuration 通过配置

You can add you client key and certificate to your JVM KeyStore, it should be picked up at Runtime when the server asks for your client-side SSL authentication. 您可以将客户端密钥和证书添加到JVM KeyStore中,当服务器要求您进行客户端SSL身份验证时,应该在运行时将其提取。 (SSL/TLS is designed for that : the server will ask for a client certificate that is signed by it's trusted authority, which allows the SSL Engine to choose the right certificate, even when your KeyStore holds many). (SSL / TLS是为此目的而设计的:服务器将请求由其可信授权机构签名的客户端证书,即使您的KeyStore拥有很多证书,SSL引擎也可以选择正确的证书)。

Through Code 通过代码

You can roll you own SSLContext using custom made KeyStore / TrustStore s. 您可以使用定制的KeyStore / TrustStore滚动自己的SSLContext This is a bit complex (I won't elaborate on how to build Keystore instances in Java), but the gist of it is here : 这有点复杂(我不会详细说明如何在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 !
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM