如何使用HTTP客户端传递客户端证书?

我想在服务A和B之间使用相互SSLauthentication。我目前正在实现从Java中的服务A传递客户端证书。 我正在使用Apache DefaultHttpClient执行我的请求。 我能够从内部凭证pipe理器检索我的服务A的客户端证书,并将其保存为一个字节数组。

DefaultHttpClient client = new DefaultHttpClient(); byte [] certificate = localCertManager.retrieveCert(); 

我在这方面的经验很less,我很感激你的帮助!

我想也许它应该以某种方式通过在HTTP客户端或可能在标题中的parameter passing。

如何使用HTTP客户端传递客户端证书?

您需要告诉SSLSocketFactory(org.apache.http,而不是javax)您的密钥库,并将DefaultHTTPClient配置为将其用于https连接。

这里是一个例子: http : //hc.apache.org/httpcomponents-client-ga/httpclient/examples/org/apache/http/examples/client/ClientCustomSSL.java

客户端证书在建立连接时在TLS握手期间发送,并且不能通过该连接中的HTTP发送。

沟通是这样分层的:

  • HTTP(应用层协议)内
  • TLS(表示层协议)内
  • TCP(传输层协议)内
  • IP(网络层协议)

您需要在TLS握手期间发送客户端证书,然后才能影响HTTP(方法,头文件,URL,请求主体)。 服务器不会接受稍后发送的客户端证书。

我建议从DefaultHttpClient (不建议使用)切换到CloseableHttpClient ,它可以通过try-with-resources更加干净地工作。

Apache HttpClient 4.5让Mutual TLS非常方便。 这个答案已经用Apache HttpClient 4.5.3进行了测试。

基本的出发点是使用loadKeyMaterial来加载你的客户端证书,并把它的关键字(客户端密钥对)加载到SSLContext中

 SSLContext sslContext = SSLContexts.custom().loadKeyMaterial( MutualHttpsMain.class.getResource(TEST_CLIENT_KEYSTORE_RESOURCE), password, password, (aliases, socket) -> aliases.keySet().iterator().next() ).build(); 

最后,用这个套接字工厂构建一个HTTP客户端:

 CloseableHttpClient httpclient = HttpClients .custom().setSSLContext(sslContext).build(); 

使用该客户端,您的所有请求都可以使用隐含的相互TLS认证来执行:

 CloseableHttpResponse closeableHttpResponse = httpclient.execute( new HttpGet(URI.create("https://mutual-tls.example.com/"))); 

下面是Apache HttpClient相互TLS的完整运行示例:

 import org.apache.http.HttpEntity; import org.apache.http.StatusLine; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.apache.http.ssl.SSLContexts; import javax.net.ssl.SSLContext; import java.io.Console; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.nio.ByteBuffer; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import java.security.GeneralSecurityException; public class MutualHttpsMain { private static final String TEST_URL = "https://mutual-tls.example.com/"; private static final String TEST_CLIENT_KEYSTORE_RESOURCE = "/mutual-tls-keystore.p12"; public static void main(String[] args) throws GeneralSecurityException, IOException { Console console = System.console(); char[] password = console.readPassword("Keystore password: "); SSLContext sslContext = SSLContexts.custom().loadKeyMaterial( MutualHttpsMain.class.getResource(TEST_CLIENT_KEYSTORE_RESOURCE), password, password, (aliases, socket) -> aliases.keySet().iterator().next() ).build(); try (CloseableHttpClient httpclient = HttpClients .custom().setSSLContext(sslContext).build(); CloseableHttpResponse closeableHttpResponse = httpclient.execute( new HttpGet(URI.create(TEST_URL)))) { console.writer().println(closeableHttpResponse.getStatusLine()); HttpEntity entity = closeableHttpResponse.getEntity(); try (InputStream content = entity.getContent(); ReadableByteChannel src = Channels.newChannel(content); WritableByteChannel dest = Channels.newChannel(System.out)) { ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024); while (src.read(buffer) != -1) { buffer.flip(); dest.write(buffer); buffer.compact(); } buffer.flip(); while (buffer.hasRemaining()) dest.write(buffer); } } } } 

通常使用Gradle或Maven来运行这样的程序通常会更好,但是为了尽可能减少这个牦牛刮脸,我提供了构建和运行这个的基准JDK指令。

从以下页面下载JAR:

  • Apache HttpClient 4.5.3
  • Apache Commons Codec 1.10
  • Apache Commons Logging 1.2
  • Apache HttpCore 4.4.8

将上面的完整示例保存为MutualHttpsMain.java

将PKCS#12复制到相同目录下的mutual-tls-keystore.p12

编译如下(在macOS / Linux / * nix-likes):

 javac MutualHttpsMain.java -cp httpclient-4.5.3.jar:httpcore-4.4.8.jar 

或在Windows上:

 javac MutualHttpsMain.java -cp httpclient-4.5.3.jar;httpcore-4.4.8.jar 

运行如下(在macOS / Linux / * nix-likes)上:

 java -cp httpclient-4.5.3.jar:commons-codec-1.10.jar:commons-logging-1.2.jar:httpcore-4.4.8.jar:. MutualHttpsMain 

运行如下(在Windows上):

 java -cp httpclient-4.5.3.jar;commons-codec-1.10.jar;commons-logging-1.2.jar;httpcore-4.4.8.jar;. MutualHttpsMain