我正在尝试连接到HTTPS URL,但是我需要使用客户端身份验证和第三方软件放在我的系统上的证书.

我没有丝毫的想法,我应该如何查找或使用它,我所要做的只是C#示例代码,这与我发现的所有Java答案有很大的不同. (例如,KeyStore是否需要某种密码?)

这是我拥有的C#示例代码

System.Security.Cryptography.X509Certificates.X509CertificateCollection SSC_Certs =
new System.Security.Cryptography.X509Certificates.X509CertificateCollection();
Microsoft.Web.Services2.Security.X509.X509CertificateStore WS2_store =
Microsoft.Web.Services2.Security.X509.X509CertificateStore.CurrentUserStore(
Microsoft.Web.Services2.Security.X509.X509CertificateStore.MyStore);
WS2_store.OpenRead();
Microsoft.Web.Services2.Security.X509.X509CertificateCollection WS2_store_Certs = WS2_store.Certificates;
然后它只是遍历WS2_store_Certs CertificateCollection,并以这种方式进行检查.
再进一步,它设置了这样的证书:
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(url_string);
httpWebRequest.ClientCertificates = SSC_Certs;

这一切看起来相当合乎逻辑,即使我不知道它如何找到证书,但是我仍然找不到Java的等同物.

UPDATE

我正在制作的连接是依赖于JDK 5的较大应用程序的一部分,但是我已经设法使用sunmscapi jar找到我正在寻找的证书.当我尝试使用Windows密钥库连接时出现错误,所以我以为我从Windows存储中获取我需要的证书并将其插入到默认java中,因此我想到了这个问题.现在我得到一个EOFException,然后是SSLHandshakeException,说“远程主机在握手期间关闭连接”. ssl调试跟踪并没有显示立即的问题,因为我需要的证书显示在证书链中.

它完成了整个ClientKeyExchange的事情,说完了,然后我从调试日志中得到的最后一个消息就是

[write] MD5 and SHA1 hashes: len = 16
0000: 14 00 00 0C D3 E1 E7 3D C2 37 2F 41 F9 38 26 CC .......=.7/A.8&.
Padded plaintext before ENCRYPTION: len = 32
0000: 14 00 00 0C D3 E1 E7 3D C2 37 2F 41 F9 38 26 CC .......=.7/A.8&.
0010: CB 10 05 A1 3D C3 13 1C EC 39 ED 93 79 9E 4D B0 ....=....9..y.M.
AWT-EventQueue-1, WRITE: TLSv1 Handshake, length = 32
[Raw write]: length = 37
0000: 16 03 01 00 20 06 B1 D8 8F 9B 70 92 F4 AD 0D 91 .... .....p.....
0010: 25 9C 7D 3E 65 C1 8C A7 F7 DA 09 C0 84 FF F4 4A %..>e..........J
0020: CE FD 4D 65 8D ..Me.
AWT-EventQueue-1, received EOFException: error

而我正在使用的代码来建立连接

KeyStore jks = KeyStore.getInstance(KeyStore.getDefaultType());
jks.load(null, null);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
jks.setCertificateEntry("alias", cert1); //X509Certificate obtained from windows keystore
kmf.init(jks, new char[0]);
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(kmf.getKeyManagers(), new TrustManager[]{tm}, null);
sslsocketfactory = sslContext.getSocketFactory();
System.setProperty("https.proxyHost", proxyurl);
System.setProperty("https.proxyPort", proxyport);
Authenticator.setDefault(new MyAuthenticator("proxyID", "proxyPassword"));
URL url = new URL(null, urlStr, new sun.net.www.protocol.https.Handler());
HttpsURLConnection uc = (HttpsURLConnection) url.openConnection();
uc.setSSLSocketFactory(sslsocketfactory);
uc.setAllowUserInteraction(true);
uc.setRequestMethod("POST");
uc.connect();

(我还没有尝试HttpClient,因为我不知道如何找到证书文件,我也不知道这在每个客户端系统上是否一样).

另一个更新

我在WINDOWS-ROOT密钥库中找到了我需要的证书的CA(并使用.verify()检查它们是否已经检出),我也将它们添加到了java密钥库中,但仍然没有任何变化.我想他们应该进入TrustStore,但是我还没有找到一种方法来编程. (不想依靠最终用户做这样的事情,因为我可以保证的是证书和CA将由于在这个可笑的漫长问题开始时提到的第三方软件而存在).

更多更新

加上以前的更新,我得出结论,我的问题必须在于我的CA不在Java的cacerts文件中,所以它从服务器获取可信CA的列表,但不能识别它们随后不会发送单个证书,导致连接失败.

所以问题依然存在,如何让Java将密钥库用作信任库或以编程方式添加证书到Cacerts(而不需要文件路径)?因为如果那些不可能只是让我秘密选择C,巫毒.我会用针头刺一个公爵娃娃,以防万一.