如何在HttpsURLConnection中使用证书身份验证?

我正在尝试连接到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。

我建立的连接是依赖于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,即

voodoo 。为了防万一,我将开始用针刺伤杜克娃娃。

回答:

事实证明这是一个私钥问题,因为它被设置为不可导出。因为这意味着我只能从Windows商店中获取私钥,所以我花了很多时间弄乱并“解决”了这个问题,以使必要的jdk6类正常工作,而又不会对应用程序的其余部分造成太大影响。

以上是 如何在HttpsURLConnection中使用证书身份验证? 的全部内容, 来源链接: utcz.com/qa/428317.html

回到顶部