如何在JaxWsProxyFactoryBean中启用SSL支持?
JaxWsProxyFactoryBean 启用SSL配置实现
JaxWsProxyFactoryBean是Apache CXF提供的WebService客户端代理工厂,SSL配置核心是给代理底层的HTTP传输管道HTTPConduit挂载自定义TLS参数,具体实现步骤如下:
- 初始化代理对象后,从代理实例中取出底层
Client实例,获取对应的HTTPConduit - 构造
TLSClientParameters对象,根据场景配置信任库、客户端证书库、SSL上下文 - 将配置好的TLS参数设置到
HTTPConduit中即可生效
完整可运行代码示例:
import org.apache.cxf.configuration.jsse.TLSClientParameters; import org.apache.cxf.endpoint.Client; import org.apache.cxf.frontend.ClientProxy; import org.apache.cxf.jaxws.JaxWsProxyFactoryBean; import org.apache.cxf.transport.http.HTTPConduit; import javax.net.ssl.KeyManagerFactory; import javax.net.ssl.SSLContext; import javax.net.ssl.TrustManagerFactory; import java.io.FileInputStream; import java.security.KeyStore; import java.security.SecureRandom; public class SSLWsClientDemo { public static void main(String[] args) throws Exception { // 1. 初始化代理工厂、生成服务代理对象 JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean(); factory.setServiceClass(YourServiceInterface.class); factory.setAddress("https://your-webservice-endpoint-address"); YourServiceInterface serviceProxy = (YourServiceInterface) factory.create(); // 2. 从代理对象获取底层HTTP传输管道 Client client = ClientProxy.getClient(serviceProxy); HTTPConduit httpConduit = (HTTPConduit) client.getConduit(); // 3. 初始化TLS配置参数 TLSClientParameters tlsParams = new TLSClientParameters(); // 仅本地调试可临时开启主机名校验关闭,生产环境严禁使用 // tlsParams.setDisableCNCheck(true); // 加载信任库:存放信任的服务端证书/CA根证书 KeyStore trustStore = KeyStore.getInstance("JKS"); try (FileInputStream trustStoreStream = new FileInputStream("/path/to/your/truststore.jks")) { trustStore.load(trustStoreStream, "your-truststore-password".toCharArray()); } TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); trustManagerFactory.init(trustStore); // 双向认证场景需要额外加载客户端密钥库:存放客户端自身证书,供服务端校验 KeyStore clientKeyStore = KeyStore.getInstance("JKS"); try (FileInputStream keyStoreStream = new FileInputStream("/path/to/your/client-keystore.jks")) { clientKeyStore.load(keyStoreStream, "your-keystore-password".toCharArray()); } KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(clientKeyStore, "your-client-key-password".toCharArray()); // 构造SSL上下文并挂载到TLS参数 SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom()); tlsParams.setSSLSocketFactory(sslContext.getSocketFactory()); // 将TLS配置绑定到HTTP传输管道 httpConduit.setTlsClientParameters(tlsParams); // 后续直接调用serviceProxy的方法即可走SSL协议请求 } // 替换为你自己的WebService接口定义 private interface YourServiceInterface {} }
注意:以下操作仅限本地调试使用,禁止生产环境开启:
- 调用
setDisableCNCheck(true)关闭服务端证书主机名校验- 自定义实现无条件信任所有证书的
X509TrustManager
上述操作会绕过SSL证书校验,存在极大的中间人攻击风险。
常见场景简化配置
- 访问公网正规CA签发证书的HTTPS接口:不需要手动加载证书库,直接使用JDK默认的SSL上下文即可,核心代码仅需3行:
TLSClientParameters tlsParams = new TLSClientParameters(); tlsParams.setSSLSocketFactory(SSLContext.getDefault().getSocketFactory()); httpConduit.setTlsClientParameters(tlsParams); - Spring容器托管场景:可以在代理Bean创建完成后,通过
BeanPostProcessor或者@PostConstruct生命周期方法统一配置TLS参数,不需要每次生成代理时重复配置。 - 双向认证场景:必须同时加载客户端密钥库和信任库,缺少任意一个都会导致SSL握手失败。
内容的提问来源于stack exchange,提问作者Ashish Siwal
相关产品推荐
相关产品推荐

