您需要在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 **不起作用。 –