调用wcf

时间:2017-12-11 14:17:48

标签: java security keystore tls1.2 jce

我知道有很多类似的问题,但我在之前的任何问题中找不到任何帮助。我正在尝试与来自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

1 个答案:

答案 0 :(得分:0)

看起来问题是我的本地存储中有许多证书,根据我的研究,KeyManager选择符合条件的第一个Key,这意味着它不一定会在其中选择我的证书。我通过在X509KeyManager上创建一个选择我所需证书别名的装饰器来解决这个问题。从这个QA中得到了这个想法:

How I can tell alias of the wanted key-entry to SSLSocket before connecting?