我正在使用Java SE Jersey客户端连接到使用双向SSL的HTTPS资源。
我的SSLContext
如下:
private SSLContext getSSLContext() {
SslConfigurator sslConfig = SslConfigurator.newInstance()
.keyStoreFile("src/main/certificates/testcert.p12")
.keyPassword("mypassword");
return sslConfig.createSSLContext();
}
问题是客户端证书永远不会发送。
我收到错误消息“警告:未找到合适的证书-在没有客户端身份验证的情况下继续进行”,并且我已经跟踪了以下事实:客户端证书未颁发给服务器中列出的证书颁发机构之一向客户端发送CertificateRequest 消息。通过cURL
的测试,我知道服务器无论如何都会接受证书。端点是一个公共测试系统。
我的问题:如何强制发送客户证书?(即Java SE客户应忽略以下事实:testcert.p12
证书的颁发者不在以下列表中:服务器已表示会接受)
请不要向我指出有关禁用服务器证书检查或使用自签名证书的答案。服务器的证书就可以了。
原来我的问题是另外一个。我通过设置系统属性javax.net.debug=all
进行调试。在检查了结果输出之后,即使执行了上述操作,它也仍然看起来像密钥库为空。因此,难怪为什么“找不到合适的证书”。
Jersey有一个“聪明” SslConfigurator
类,可以帮助您设置SSLContext
。也许对我来说太聪明了,因为我无法使其与上面的代码一起使用。因此,我现在将SSLContext
配置如下:
KeyStore ks = KeyStore.getInstance("PKCS12");
FileInputStream fis = new FileInputStream("src/main/certificates/testcert.p12");
ks.load(fis, "mypassword".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "mypassword".toCharArray());
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(kmf.getKeyManagers(), null, null);
// now use 'sc' in Jersey
这对我有用,而泽西岛的助手班却没有。我完全同意Jersey提出的SSLContext辅助类的想法,因为对于这样一个简单的用例,JSSE在这里似乎过于复杂。好吧,好吧。
答案 0 :(得分:2)
不能。这将违反TLS协议,因此没有支持它的API。各种TLS API仅在以下情况下才会发送客户端证书:
CertificateRequest
消息中指定内容的客户端证书。您必须安排服务器信任您的客户端证书,方法是通过CA对其进行签名,或者将其导出到服务器的受信任证书存储中,无论服务器采用哪种形式。