我有
现在我需要使用这些证书通过HTTPS发送POST请求。 我在浏览器中安装后,设法在Internet Explorer中通过https测试连接:
在java中,直到现在我使用 neu242 在答案中SO: Java client certificates over HTTPS/SSL中给出的代码,即接受任何证书。但现在服务器端确实接受了这一点,即我获得了SSL握手失败。
感谢SO: X509TrustManager Override without allowing ALL certs?我试图在getAcceptedIssuers
中返回服务器证书,但是徒劳无功。它抛出
在javax.net.ssl.SSLHandshakeException:收到致命警报:handshake_failure
getAcceptedIssuers
返回后。
public X509Certificate[] getAcceptedIssuers() {
try {
X509Certificate scert;
try (InputStream inStream = new FileInputStream("..\\server.crt")) {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
scert = (X509Certificate) cf.generateCertificate(inStream);
}
return new X509Certificate[]{scert};
} catch (Exception ex) {
writeLogFile(ex.getMessage());
return new X509Certificate[]{};
}
}
我想我应该以某种方式指定客户端证书,但找不到任何方法。 我当然可能是错的。
希望有人能指引我正确的方向。
答案 0 :(得分:0)
最后我设法让它发挥作用。
由于服务器证书是自签名的,我不得不将其放入信任库。为避免将其添加到常见的JRE cacerts,我使用以下命令将其放入单独文件的信任库中(感谢Common SSL issues in Java:
keytool -import -v -trustcacerts
-file servercert.crt -keystore server.jks
-keypass mypwd -storepass mypwd
然后,我使用获取的信任库和包含密钥的客户端证书来初始化密钥库并将其指定到SSL上下文(感谢sql.ru: Received fatal alert: handshake_failure):
String pwd = "mypwd";
InputStream keyStoreUrl = new FileInputStream("client.p12");
InputStream trustStoreUrl = new FileInputStream("server.jks");
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(keyStoreUrl, pwd.toCharArray());
KeyManagerFactory keyManagerFactory =
KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, pwd.toCharArray());
KeyStore trustStore = KeyStore.getInstance("JKS");
trustStore.load(trustStoreUrl, pwd.toCharArray());
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
final SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(keyManagerFactory.getKeyManagers(),
trustManagerFactory.getTrustManagers(),
new SecureRandom());
SSLContext.setDefault(sslContext);
此外,我必须指定HostnameVerifier
,因为与服务器证书和此服务器的网址存在一些不一致:
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
//...
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
就是这样。更进一步,它就像:
url = new URL(targetURL);
connection = (HttpsURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type",
"application/x-www-form-urlencoded;charset=utf-8");
connection.setRequestProperty("Accept", "application/x-www-form-urlencoded");
connection.setRequestProperty("Accept-Charset", "UTF-8");
connection.setRequestProperty("Content-Length",
Integer.toString(Data.getBytes("utf8").length));
connection.setDoInput(true);
connection.setDoOutput(true);
connection.getOutputStream().write(Data.getBytes("utf8"));
// read response...