我正在尝试为特定的Web服务调用设置SSLContext。目的是通过编程方式为呼叫指定客户端证书(在具有自签名证书的服务器中)。
我从this post那里得到了一些想法:
SSLContext sc = SSLContext.getInstance("TLS");
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore ks = KeyStore.getInstance("JKS");
//...
ks.load(is, "passw".toCharArray());
kmf.init(ks, "passw".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
//...
tmf.init(ts);
sc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
com.ex.Ex service = new com.ex.Ex();
com.ex.ExService port = service.getDataServiceImplPort();
BindingProvider bp = (BindingProvider) port;
Map<String, Object> context = bp.getRequestContext();
context.put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", sc.getSocketFactory());
text = port.callWS();
我的代码不应依赖于任何特定的JVM(不确定com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory
是否在特定的JVM上失败)。
第一个障碍是我遇到了这个错误:
Caused by: java.security.SignatureException: Signature does not match.
at sun.security.x509.X509CertImpl.verify(X509CertImpl.java:424)
at sun.security.provider.certpath.BasicChecker.verifySignature(BasicChecker.java:166)
at sun.security.provider.certpath.BasicChecker.check(BasicChecker.java:147)
at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(PKIXMasterCertPathValidator.java:125)
... 98 more
哪个告诉我未使用信任库。
我还创建了具有相同结果的own dummy validator。因此,看来context.put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory", sc.getSocketFactory());
尚未设置。
我可以通过使用System属性来全局设置信任库来覆盖此设置,但是不使用任何密钥库。我还可以设置一个密钥库,但这将在全局范围内完成,因此这是通过编程方式设置客户端证书的唯一目的。