如何在Axis2 Java客户端中使用自签名证书?

3

我使用org.codehaus.mojo axistools-maven-plugin插件版本1.4生成了代码。我正在尝试通过https连接到web服务。我已经将服务器证书安装到jssecacerts中,并将此密钥库复制到/System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home/lib/security/文件夹中。这意味着我在客户端密钥库中拥有服务器证书。我还将服务器私钥和证书导入到kestore.ImportKey密钥库中。我猜我将不得不将其用作信任存储。现在,如何在java客户端中连接所有这些内容?我在客户端使用自动生成的存根。我尝试使用以下方法,但不起作用。

System.setProperty("javax.net.ssl.trustStore","certs/keystore.ImportKey");
System.setProperty("javax.net.ssl.trustStorePassword", "importkey"); 

我遇到了以下异常。

faultString: javax.net.ssl.SSLHandshakeException: 
    sun.security.validator.ValidatorException: 
PKIX path building failed: 
    sun.security.provider.certpath.SunCertPathBuilderException:
     unable to find valid certification path to requested target

证书是有效的,因为我正在使用相同的证书在HTTPS客户端上用于相同的主机。此外,我能够看到使用相同的证书成功的curl请求。实际上,我不确定如何使用自签名服务器证书编写Axis2 soap Java客户端来访问https。有人能给我指出一个逐步示例吗?
2个回答

2
在客户端,您不需要证书私钥来信任服务器。由于您在问题中提到已经通过 keystore.ImportKey 导入了证书和密钥,我认为它们已经作为PrivateKeyEntry导入(您可以使用keytool验证 keystore 中的条目类型)。
然而,如果您想将证书用作信任锚点,您应该将证书作为TrustedCertificateEntry导入。这可以使用keytool实现:
keytool -importcert -trustcacerts -alias myTrustAnchor -file /path/to/cert.crt -keystore /path/to/keystore

然后您可以在应用程序中配置信任存储:

System.setProperty("javax.net.ssl.trustStore","/path/to/keystore");

2

感谢 @Jcs

这是我解决问题的方法。当我尝试在浏览器中打开webservice URL时,它要求提供客户端证书。这意味着,因为我已经在jvm中的jssecacert中导入了服务器证书,我的客户端缺少客户端证书。所以,我设置了javax.net.ssl.keyStorejavax.net.ssl.keyStorePassword属性,而不是设置javax.net.ssl.trustStorejavax.net.ssl.trustStorePassword属性,现在它可以正常工作了。我之前错过了将私钥和证书导入密钥库的事实。ImportKey基本上是我很久以前从某人那里收到的客户端身份标识,他说那些是服务器证书,这让我产生了误导。因此,如果有人正在寻找解决方案,让我总结一下。

  1. 下载服务器证书并将其导入到JVM cacerts或系统路径上的jssecacerts中。 我使用了这篇文章

  2. 在浏览器中打开webservice URL,如果它要求提供客户端证书,则表示服务器已设置为期望从客户端接收证书。在自签名证书的情况下,您必须已经拥有来自服务器的自签名证书。将其导入到密钥库中,并在实际调用web服务之前设置密钥库的系统属性,如下所示。这是因为您已经将服务器证书导入了客户端信任存储(cacerts)。

代码:

MySoap12Stub stub = (MySoap12Stub) new MyLocator().getMySoap12(new java.net.URL(WSUrl));

System.setProperty("javax.net.ssl.keyStore", "certs/keystoreQA.Importkey");
System.setProperty("javax.net.ssl.keyStorePassword", "importkey");

在我的情况下,服务器期望用户令牌和密码设置到SOAP头中。以下是我如何将其设置到SOAP头中:

((Stub) stub).setHeader(HeaderHandler.getSecurityHeader(User, password));

public class HeaderHandler {

    public static SOAPHeaderElement getSecurityHeader(String user,String password) throws Exception {
        SOAPHeaderElement wsseSecurity = new SOAPHeaderElement(new PrefixedQName(
            "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd",
            "Security", "wsse"));
        wsseSecurity.setActor(null);
        wsseSecurity.setMustUnderstand(true);

        SOAPElement usernameToken = wsseSecurity.addChildElement("UsernameToken", "wsse");
        usernameToken.setAttribute("xmlns:wsu","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");
        SOAPElement username = usernameToken.addChildElement("Username", "wsse");
        username.addTextNode(user);

        SOAPElement password = usernameToken.addChildElement("Password", "wsse");
        password.setAttribute("Type","http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText");
        password.addTextNode(password);
        return wsseSecurity;
    }
} 

我希望这篇文章详细说明了如何在使用WSSE用户令牌和密码的情况下,使用自签名证书来调用通过https连接的Web服务的Axis2客户端。

干杯!现在可以开始了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接