2012-04-16 273 views
2

我有以下问题。我有一个webservice,它具有可以通过SSL调用的端点,还有一些只能通过使用客户端证书来对客户端进行身份验证才能调用。问题是我想动态更改客户端证书。 我的代码是:Java web服务客户端,动态更改客户端证书

System.setProperty("javax.net.ssl.trustStore", "cacerts.jks"); 
System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); 
//... 
// first web service call, without client side certificate -> OK 
//... 
System.setProperty("javax.net.ssl.trustStore", "cacerts.jks"); 
System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); 
System.setProperty("javax.net.ssl.keyStore", "keystore1.jks"); 
System.setProperty("javax.net.ssl.keyStoreType", "JKS"); 
System.setProperty("javax.net.ssl.keyStorePassword", "password"); 
//... 
// second web service call 

我的问题是在第二个电话。在这里,我得到一个异常:

javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure 

如果我只运行的代码一切的第二部分是好的,它完美的作品(所以我有 keystore.jks与客户端证书,服务器做正确验证我的请求)。我究竟做错了什么?如何在调用webservices时动态更改客户端证书?

回答

3

我怀疑正在发生的事情是您正在使用某种方法将其默认JSSE SSLContext用于其SSL套接字工厂。从documentation看来,SSL上下文仅在首次创建时才配置一次,并且在第一次使用后设置系统属性不起作用。

我推荐使用Apache HttpClient。他们的SSLSocketFactory实现允许编程定制密钥库和信任库以用于与该工厂进行的连接。最重要的是,HttpClient为您提供了比JDK提供的更多功能和配置选项。

+0

+1同意。 SSL上下文只被配置一次 – jaxb 2012-04-17 05:00:03

+0

我试图使用他们的SSLSocketFactory,但它与'javax.net.ssl.SSLSocketFactory'不兼容。我得到一个'ClassCastException': 'org.apache.http.conn.ssl.SSLSocketFactory不能转换为javax.net.ssl.SSLSocketFactory' 那么最简单的方法是什么? – hpityu 2012-04-17 11:16:56

+1

@hpityu您正在使用什么库来进行Web服务调用?您将无法将Apache'SSLSocketFactory'实例放置到需要'javax.net.ssl.SSLSocketFactory'的某个位置。它被设计用于Apache提供的'HttpClient'。根据您的应用程序,您可能(1)重写您的客户端代码以使用'HttpClient',或者(2)编写一个适配器来包装Apache'SSLSocketFactory'以实现'javax.net.ssl.SSLSocketFactory'。 – Alex 2012-04-17 17:17:39