我拥有客户端证书和CA证书,并且按照本教程进行操作以生成相应的p12
文件和jks
文件。
我运行了以下命令来生成上述文件:
openssl pkcs12 -export -in client.crt -inkey client.key -out client.p12 -name "pandb_client"
->这给了我client.p12
文件
keytool -genkey -dname "cn=CLIENT" -alias storekey -keyalg RSA -keystore ./store.jks -keypass changeit -storepass changeit
->这给了我store.jks
keytool -import -keystore ./store.jks -file ca.crt -alias client
->我将CA导入到新创建的JKS中
代码如下:
import okhttp3.*;
import org.apache.http.ssl.SSLContexts;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.*;
import java.security.cert.CertificateException;
import java.time.Duration;
final class ConnectUsingSSL {
private static final String CA_KEYSTORE_TYPE = KeyStore.getDefaultType(); //"JKS";
private static final String CA_KEYSTORE_PATH = "store.jks";
private static final String CA_KEYSTORE_PASS = "changeit";
private static final String CLIENT_KEYSTORE_TYPE = "PKCS12";
private static final String CLIENT_KEYSTORE_PATH = "client.p12";
private static final String CLIENT_KEYSTORE_PASS = "changeit";
public static void main(String[] args) throws KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException, KeyManagementException, UnrecoverableKeyException {
SSLContext context = createSslCustomContext();
final OkHttpClient okHttpClient = new OkHttpClient.Builder().
readTimeout(Duration.ofMillis(60000L)).
connectTimeout(Duration.ofMillis(60000L)).
callTimeout(Duration.ofMillis(60000L)).
retryOnConnectionFailure(Boolean.TRUE).
sslSocketFactory(context.getSocketFactory(), (X509TrustManager) getTrustManager()[0]).
hostnameVerifier((hostname, session) -> true).
build();
RequestBody requestBody = RequestBody.create("{\"query\": {\"urls\": [\"google.com\", \"yahoo.com\", \"facebook.com\"]}}",
MediaType.parse("application/json; charset=utf-8"));
Request request = new Request.Builder().
url("https://somehost:443/query_urls").
post(requestBody).
build();
try (Response response = okHttpClient.newCall(request).execute()) {
if (!response.isSuccessful()) throw new IOException("Unexpected code " + response.body().string());
System.out.println(response.body().string());
} catch (IOException e) {
e.printStackTrace();
}
}
private static SSLContext createSslCustomContext() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException, UnrecoverableKeyException {
// Trusted CA keystore
KeyStore tks = KeyStore.getInstance(CA_KEYSTORE_TYPE);
tks.load(new FileInputStream(CA_KEYSTORE_PATH), CA_KEYSTORE_PASS.toCharArray());
// Client keystore
KeyStore cks = KeyStore.getInstance(CLIENT_KEYSTORE_TYPE);
cks.load(new FileInputStream(CLIENT_KEYSTORE_PATH), CLIENT_KEYSTORE_PASS.toCharArray());
return SSLContexts.custom()
.loadKeyMaterial(cks, CLIENT_KEYSTORE_PASS.toCharArray())
.build();
}
private static TrustManager[] getTrustManager() throws KeyStoreException, IOException, CertificateException, NoSuchAlgorithmException {
// Trusted CA keystore
KeyStore tks = KeyStore.getInstance(CA_KEYSTORE_TYPE);
tks.load(new FileInputStream(CA_KEYSTORE_PATH), CA_KEYSTORE_PASS.toCharArray());
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(tks);
return tmf.getTrustManagers();
}
}
我花了7个多小时来尝试完成这项工作,但是我未能提供任何帮助,我们深表感谢。
来自服务器的响应:
java.io.IOException: Unexpected code <html>
<head><title>400 No required SSL certificate was sent</title></head>
<body bgcolor="white">
<center><h1>400 Bad Request</h1></center>
<center>No required SSL certificate was sent</center>
<hr><center>nginx/1.12.2</center>
</body>
</html>
导入套接字 导入ssl
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ssl_sock = ssl.SSLSocket(sock=s, ssl_version=ssl.PROTOCOL_TLSv1,
certfile="client.crt", keyfile="client.key",
server_hostname="queryurls")
ssl_sock.connect(("somehost", 443))
body = '{"query": {"urls": ["google.com", "yahoo.com", "facebook.com"]}}'
rqst = "POST /query_urls HTTP/1.1\r\nHost: queryurls\r\nContent-Type: application/json\r\nContent-Length: %d\r\nConnection: keep-alive\r\n\r\n%s" % (len(body), body)
ssl_sock.sendall(rqst)
#you should process the HTTP reply header to retrieve the reply body length
#and keep reading until you receive the full reply body.
print rqst
reply = ssl_sock.recv(16384);
print reply
当我运行上面的Python代码时,相同的客户端证书和CA可以很好地工作,不确定如何在JAVA中复制它。