您需要在TLS握手期间发送客户端证书可以影响HTTP(方法,头文件,URL,请求主体)。服务器不会接受稍后发送的客户端证书。
我推荐从DefaultHttpClient开关(不建议使用)到CloseableHttpClient与尝试,与资源更清洁工作。
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/")));
这里的相互TLS的与Apache HttpClient的一个完整的可运行的例子:
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);
}
}
}
}
它通常最好使用摇篮或Maven运行这样的事情,但在保持这个牦牛剃须的利益尽可能最小化我提供基线JDK指令来构建和运行此指令。从以下页面
下载JAR文件:
保存上面的完整的例子为MutualHttpsMain.java。
将您的PKCS#12复制到mutual-tls-keystore.p12在同一目录中。
编译如下(在Mac OS/Linux的/ * nix中-喜欢):
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
运行如下(在Mac OS/Linux的/ * nix-喜欢):
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
很酷,这真的很有帮助! – agerrr
这开始是模糊的,但链接的示例通过不使用客户端证书来混淆事物。它实际上设置了替代的CA证书来替代正在连接的服务器,但是对于不熟悉** SSLContexts **的人来说,这可能是一个正确的例子。我遵循这一点,并花了很多时间来解决** loadTrustMaterial **不起作用。 –