2011-06-07 57 views
3

我试图从Web服务请求客户端提交客户端证书的数据。服务器使用SSL进行所有通信,并使用自签名证书。我向Netbeans提供了该服务的WSDL文件,并生成了带有wsimport的客户端代码。将Glassfish配置为使用双向SSL的Web服务的客户端

当我的客户端代码写入常规Java应用程序时,我没有任何问题;我将信任库设置为包含服务器证书的cacerts文件,将密钥库设置为服务器管理员以JKS格式提供的包含2个密钥的文件 - 客户机私钥和服务器的公钥,构建请求对象,以及发送请求。

将问题转移到企业Java环境时出现问题。要求规定代码必须是在Glassfish应用程序服务器上运行的Enterprise Archive内的Enterprise JavaBean。看起来Glassfish有自己的安全设置来覆盖JVM的设置。当包含Web服务调用的EJB方法运行时,SSL协商失败: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。我不知道如何像我的JVM的设置一样设置Glassfish的安全设置,任何人都可以解释Glassfish的安全设置吗?我所做的研究仅显示了如何将Glassfish设置为Web服务服务器,而不是Web服务客户端

我有一个服务器的.cer证书文件,我通过使用Java的keytool将其添加到默认的cacerts文件中,将它添加到我的信任存储中。 如果将cacerts文件修改为InstallCert以包含自签名证书,请按照http://blog.johnryding.com/post/1548502059/acquire-an-ssl-certificate-for-your-java-programs-in-win的步骤更好地修改?

我有存储在$ JAVA_HOME/jre/lib/security和$ JAVA_HOME/lib/security中的信任存储文件,密钥存储文件以及.cer证书文件和.p12浏览器证书。

我使用Netbeans 6.9.1和Glassfish 3.1 Final。相关的一段代码如下,从我的EJB中复制而来。最后一行发生异常。

System.setProperty("javax.net.ssl.trustStore", "C:\\jssecacerts"); System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); System.setProperty("javax.net.ssl.keyStore", "C:\\userCertificate.jks"); System.setProperty("javax.net.ssl.keyStorePassword", "password");
RequestObject request = new RequestObject;
request.setQuery("some data");
request.setUsername("user");
request.setPassword("pass");
Service service = new Service();
Endpoint port = service.getWebServicePort();
Result result = port.specificWebServiceMethod(request);

+0

你解决了这个问题吗?我面对同样的情况。如果你有东西,请提供详细信息。 – mahesh 2011-11-18 11:43:12

回答

1

而不是使用全局系统属性的,你应该为你的客户端的独立SSLContext。那么它是否在Glassfish服务器中运行并不重要。

下面是应该是相关的(有关客户证书WS)一个问题:Choosing SSL client certificate in Java

1

我有这个确切的问题(与Glassfish的3.0.1)。

下面是我们解决这个问题的确切步骤。

    • 一个。使用java keytool命令查看密钥库以查看密钥库中的内容。这有助于稍后查看是否有任何更改。命令有点像

      keytool -list -keystore MyKeyStore.jks 
      
    • b。使用openssl将pfx转换为pem。请注意,我为输入pfx使用了正确的密码,并且对于pem文件输出使用了与我的java密钥库相同的密码。

      openssl pkcs12 -in MyPfxFile.pfx -out MyPemFile.pem 
      
  1. PEM文件转换为可以容易地导入到Java密钥为P12。请注意,我在我的java密钥库中使用了与输入和输出文件相同的密码。

    openssl pkcs12 -export -in MyPemFile.pem -out MyP12File.p12 
    
  2. 现在我最后将p12导入到我的java密钥库中。请注意,我使用java 6,java 5 keytool不支持-importkeystore参数。

    keytool -importkeystore -deststorepass MyPassword -destkeystore PathToMyKeystore/keystore.jks -srckeystore MyP12File.p12 -srcstoretype PKCS12 -srcstorepass MyPassword 
    
  3. 你可以在这里列出密钥库的内容,像这样的keytool -list -keystore keystore.jks只是为了确保你的新的关键是正确导入。

如果你像我一样幸运,你会发现在这一点上启动你的应用服务器将是没有用的。你会看到有关pkix路径或HTTP 403 Forbidden的一些错误。

以上使用的步骤完美适用于Sun Application Server 9.1_1,但不适用于Oracle Glassfish 3.0.1。我认为这与第3部分中使用的JSSE版本相比,与Sun App Server或jdk版本相关。如果仅将客户端证书添加到密钥存储库,那么将以下jvm选项添加到您的ogs 3 domain.xml文件应该可以解决问题。

<jvm-options>-Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocol</jvm-options> 

我也注意到,有人说不要使用JVM选项上述声明,但它是固定的一部分,不使用它,看看它是否工作,我敢打赌,它不会。也许只是改变处理程序就是为什么它可以工作?

这里就是我发现的所有细节:http://onjava.com/pub/a/onjava/2001/05/03/java_security.html?page=4

我还隔着一个最终的问题(仅适用于OGS 3)迷迷糊糊的,如果你失败,现在每一次我建议寻找InstallCert应用程序(它在那里)并为其提供以下命令行参数: 每次尝试调用Web服务时,都会收到这些PKIX错误。

希望这可以帮助别人。这些类型的问题,真让我想撕毁我的头发:)

4

我面对的是,上述雅克·普里查德相同的异常:

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 

解决其导入两个cacerts的根证书。 JKS和keystore.jks,使用以下命令:

/usr/java/jdk1.6.0_25/bin/keytool -import -trustcacerts -file root_ca.cer -alias rootca -keystore cacerts.jks 

/usr/java/jdk1.6.0_25/bin/keytool -import -trustcacerts -file root_ca.cer -alias rootca -keystore keystore.jks 

它说,别名rootca是我自己定义的标记证书的名称是非常重要的。你也可以选择任何名字。

0

我终于明白了。

从我的keytool中删除了所有证书。

命令示例:keytool -list -v -keystore keystore.jks -alias mydomain

我转换证书响应从服务器到bas64 DER和复制他们到一个文件中的.PEM,我上传的.PEM到我的密钥工具:

命令示例:keytool -importcert -keystore keystore.jks -alias mydomain -file my.pem

然后我加载密钥库:

KeyStore myStore = KeyStore.getInstance("JKS"); 
InputStream keyInputx = new FileInputStream("C:\\myStore.jks"); 
myStore.load(keyInputx, "xxx".toCharArray()); 
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509"); 
keyInputx.close(); 
/*Enumeration enumeration = myStore.aliases(); 
while (enumeration.hasMoreElements()) { 
    String alias = (String) enumeration.nextElement(); 
    System.out.println("alias name: " + alias); 
    Certificate certificate = myStore.getCertificate(alias); 
    System.out.println(certificate.toString()); 
}*/ 
keyManagerFactory.init(myStore, "xxx".toCharArray()); 
SSLContext context = SSLContext.getInstance("TLS"); 
context.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom()); 
SSLSocketFactory sockFact = context.getSocketFactory(); 

大量文献的周围所以很高兴的使用。