使用SAAJ从密钥库中选择特定的客户端证书

时间:2017-10-10 17:39:20

标签: java http ssl saaj

我在SAAJ中编写了一个Java客户端,它在通过HTTP发送SOAP消息时成功运行,但是当我尝试通过HTTPS将任何SOAP消息发送到需要客户端证书的Web服务时它不起作用。

在以下链接的页面底部 - SAAJ Security - 它说明了以下内容:

从SAAJ方面,您需要做的就是使用HTTPS作为协议。仅当证书成功导入/ jre / lib / security / cacerts时,这才有效;否则JSSE将不允许连接

我按照上面的指示将客户端证书和相关的根证书导入我的Java cacerts并运行程序但是我收到以下错误:

java.net.SocketException: Connection reset

我在流量上运行了wireshark跟踪,并注意到Java代码在服务器要求时不提供客户端证书,因此我有以下问题:

1)只将HTTPS URL传递给soapConnection.call()方法并将证书导入我的cacerts文件,这是否足以进行身份​​验证,即SAAJ是否自动处理?或者是否需要在上述链接中描述的更多步骤?

2)通过将证书导入我的JAVA_HOME中的cacerts文件,Java SAAJ客户端在调用soapConnection.call()时是否自动知道在这里查看?或者我是否需要明确告诉我的代码使用什么cacerts文件?

3)如果Java SAAJ客户端自动使用我的JAVA_HOME下的cacerts文件,那么它如何知道要使用哪个客户端证书?同样,我不应该明确地编码这个或SAAJ自动处理这个吗?

提前致谢

2 个答案:

答案 0 :(得分:0)

我设法解决了这个问题。我使用了以下代码:

static public void doTrustToCertificates() throws Exception 
{

    // Set truststore that contains root / intermediary certs
    System.setProperty("javax.net.ssl.trustStore", "C:\\cert\\trusted.jks");
    System.setProperty("javax.net.ssl.trustStorePassword", "changeit");

    // Set keystore that contains private key
    File pKeyFile = new File("C:\\cert\\privatekey.pfx");
    String pKeyPassword = "Password01";
    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
    KeyStore keyStore = KeyStore.getInstance("PKCS12");
    InputStream keyInput = new FileInputStream(pKeyFile);
    keyStore.load(keyInput, pKeyPassword.toCharArray());
    keyInput.close();
    keyManagerFactory.init(keyStore, pKeyPassword.toCharArray());

    // Set ssl context with private key and truststore details
    SSLContext sc = SSLContext.getInstance("TLSv1");
    sc.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
    SSLSocketFactory sockFact = sc.getSocketFactory();

    // Add ssl context to https connection
    HttpsURLConnection.setDefaultSSLSocketFactory(sockFact);

}

然后在SAAJ的soapConnection.call()方法之前调用doTrustToCertificates()方法,它的工作原理如下:

doTrustToCertificates();
SOAPMessage soapResponse = soapConnection.call(soapMsgXml, ENDPOINT_URL);

答案 1 :(得分:0)

你没有这么指示。这些说明具有误导性,但它们仅适用于服务器证书是自签名的情况,而不适用于客户端需要证书的情况。

在这种情况下,您需要在客户端的密钥库中创建客户端证书。要么创建CSR并将其签名并使用与生成密钥对和CSR时相同的别名将其导回到同一个密钥库中,否则您需要生成自签名证书(yuck)并将其导出并将其导入服务器的信任库。

您无需编写任何代码。您需要做的就是设置系统属性javax.net.ssl.keyStore和朋友告诉JSSE您的客户端密钥库。