gpt4 book ai didi

java - 如何使用 X509 证书通过 HttpsURLConnection 进行 POST 请求?

转载 作者:太空宇宙 更新时间:2023-11-03 13:41:27 24 4
gpt4 key购买 nike

我有

  1. 自签名服务器证书(来 self 需要与之通信的第三方组织)
  2. 我的客户端证书,包含由该服务器证书签名的 key 。

现在我需要使用这些证书通过 HTTPS 发送 POST 请求。在浏览器中安装它们后,我设法在 Internet Explorer 中通过 https 测试连接:

  1. 服务器证书 - 进入受信任的 CA
  2. 客户证书 - 进入个人证书。

在 java 中,直到现在我都使用了 SO: Java client certificates over HTTPS/SSL 中给出的代码在 neu242 的回答中,即接受任何证书。但现在服务器端确实接受了这一点,即我得到 SSL 握手失败。

感谢SO: X509TrustManager Override without allowing ALL certs?我试图在 getAcceptedIssuers 中返回服务器证书,但没有成功。它抛出

javax.net.ssl.SSLHandshakeException: Received fatal alert: 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[]{};
}
}

我想我应该以某种方式指定客户端证书,但找不到任何方法。当然我可能是错的。

希望有人能指引我正确的方向。

最佳答案

最后我设法让它工作了。

由于服务器证书是自签名的,我不得不将它放入信任库中。为了避免将其添加到常见的 JRE cacerts,我使用以下命令将其放入单独文件中的信任库中(感谢 Common SSL issues in Java:

keytool -import -v -trustcacerts 
-file servercert.crt -keystore server.jks
-keypass mypwd -storepass mypwd

然后我使用获得的信任库和包含 key 的客户端证书来初始化 keystore 并将它们指定给 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,因为服务器证书和此服务器的 url 存在一些不一致:

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...

关于java - 如何使用 X509 证书通过 HttpsURLConnection 进行 POST 请求?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20627358/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com