我知道有很多类似的问题,但我在之前的任何问题中找不到任何帮助。我正在尝试与来自java客户端的wcf服务进行通信,我使用netbeans创建的自动生成的存根来实现这一点。 wcf服务使用TLS(1.2)通过客户端证书身份验证进行保护。我无法使用SunMSCAPI提供程序(意味着我想使用Windows用户本地存储将证书用作客户端。)(如果有其他方式或库可以使用Windows证书本地商店请分享我)。
此SSLContext无法调用Web服务:
IService servicePort = service.getWSHttpBindingIService();
SSLContext sslContext = SSLContext.getInstance(sslVersion);
**KeyStore keystore = KeyStore.getInstance("Windows-MY", "SunMSCAPI");
keystore.load(null, null);**
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keystore, null);
KeyManager[] keyManagers = kmf.getKeyManagers();
sslContext.init(keyManagers, null, null);
BindingProvider bindingProvider = ((BindingProvider) servicePort);
bindingProvider.getRequestContext()
.put("com.sun.xml.internal.ws.transport.https.client.SSLSocketFactory",sslContext.getSocketFactory());
我得到的错误是,在调试时我可以正确看到KeyManagers数组中的密钥和证书:
com.sun.xml.internal.ws.client.ClientTransportException: The server sent HTTP status code 403: Forbidden
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.checkStatusCode(HttpTransportPipe.java:310)
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.createResponsePacket(HttpTransportPipe.java:259)
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:217)
at com.sun.xml.internal.ws.transport.http.client.HttpTransportPipe.processRequest(HttpTransportPipe.java:130)
at com.sun.xml.internal.ws.transport.DeferredTransportPipe.processRequest(DeferredTransportPipe.java:124)
at com.sun.xml.internal.ws.api.pipe.Fiber.__doRun(Fiber.java:1121)
at com.sun.xml.internal.ws.api.pipe.Fiber._doRun(Fiber.java:1035)
at com.sun.xml.internal.ws.api.pipe.Fiber.doRun(Fiber.java:1004)
at com.sun.xml.internal.ws.api.pipe.Fiber.runSync(Fiber.java:862)
at com.sun.xml.internal.ws.client.Stub.process(Stub.java:448)
at com.sun.xml.internal.ws.client.sei.SEIStub.doProcess(SEIStub.java:178)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:93)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:77)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:147)
pfx正确安装在用户本地存储中,因为我在c#中使用它并且它工作了很多次。
在上面的java代码中,当我直接使用pfx而不是SunMSCAPI提供程序时,它可以工作:
KeyStore ks = KeyStore.getInstance("pkcs12");
ks.load(pfxStream, pfxPassword.toCharArray());
kmf.init(ks, pfxPassword.toCharArray());
我正在使用Windows 10.任何帮助都会受到关注。
我从以下链接获得了SunMSCAPi的想法: Digital Signature SunMSCAPI provider & MS Crypto API
答案 0 :(得分:0)
看起来问题是我的本地存储中有许多证书,根据我的研究,KeyManager选择符合条件的第一个Key,这意味着它不一定会在其中选择我的证书。我通过在X509KeyManager上创建一个选择我所需证书别名的装饰器来解决这个问题。从这个QA中得到了这个想法:
How I can tell alias of the wanted key-entry to SSLSocket before connecting?