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

age*_*rrr 6 apache ssl https ssl-certificate apache-commons-httpclient

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

DefaultHttpClient client = new DefaultHttpClient();
byte [] certificate = localCertManager.retrieveCert();
Run Code Online (Sandbox Code Playgroud)

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

我想也许它应该以某种方式通过HTTP客户端或可能在标头中的参数传递.

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

cov*_*ner 10

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

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

  • 开始时这大概是正确的,但是链接的示例通过不使用客户端证书而使事情变得混乱。实际上,它设置了替代的CA证书来信任与其连接的服务器,但是对于不熟悉** SSLContexts **的人来说,这似乎是一个正确的例子。我遵循了这个步骤,并花了很多时间来弄清** loadTrustMaterial **无法正常工作。 (2认同)
  • 链接已失效 (2认同)
  • 这是可能具有相同示例的链接:https://www.javatips.net/api/uw-android-master/UWPreloader/httpcomponents-client-4.5/examples/org/apache/http/examples/client/ClientCustomSSL。爪哇 (2认同)

Ala*_*Dea 7

建立连接时,客户端证书是在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();
Run Code Online (Sandbox Code Playgroud)

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

CloseableHttpClient httpclient = HttpClients
        .custom().setSSLContext(sslContext).build();
Run Code Online (Sandbox Code Playgroud)

使用该客户端,可以使用暗示的TLS相互身份验证执行所有请求:

CloseableHttpClient httpclient = HttpClients
        .custom().setSSLContext(sslContext).build();
Run Code Online (Sandbox Code Playgroud)

这是与Apache HttpClient相互TLS的完整可运行示例:

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

通常最好使用Gradle或Maven运行类似的东西,但是为了使Yak剃须刀保持最小,我提供了用于构建和运行该工具的基准JDK指令。

从以下页面下载JAR:

将上面的完整示例另存为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
Run Code Online (Sandbox Code Playgroud)

或在Windows上:

javac MutualHttpsMain.java -cp httpclient-4.5.3.jar;httpcore-4.4.8.jar
Run Code Online (Sandbox Code Playgroud)

运行如下(在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
Run Code Online (Sandbox Code Playgroud)

运行如下(在Windows上):

java -cp httpclient-4.5.3.jar;commons-codec-1.10.jar;commons-logging-1.2.jar;httpcore-4.4.8.jar;. MutualHttpsMain
Run Code Online (Sandbox Code Playgroud)