Apache Camel CXF:以编程方式添加 TlsClientParameters
Apache Camel CXF: add TlsClientParameters programmatically
我正在使用 Apache Camel CXF 作为生产者来调用 SOAP Web 服务。我不使用 Spring 配置,而是以编程方式执行所有操作(我是初学者,希望避免同时学习 Spring 和 Apache Camel)。 Web 服务使用带有自签名证书的 SSL。我将它添加到一个信任库中,并希望能够将它添加到 CxfEndpoint 中,就像我使用 https4:
所做的那样
KeyStoreParameters ksp = new KeyStoreParameters();
ksp.setResource("src/main/resources/truststore.jks");
ksp.setPassword("...");
KeyManagersParameters kmp = new KeyManagersParameters();
kmp.setKeyStore(ksp);
kmp.setKeyPassword("...");
SSLContextParameters scp = new SSLContextParameters();
scp.setKeyManagers(kmp);
CamelContext context = new DefaultCamelContext();
context.addRoutes(routeBuilder);
HttpComponent httpComponent = context.getComponent("https4", HttpComponent.class);
httpComponent.setSslContextParameters(scp);
– 但这似乎不适用于 CxfComponent。我找到了很多关于使用 Spring 添加 TlsClientParameters 和配置 CxfEndpoint 的文档,例如:
这里 。但是,我没有找到任何关于如何像使用 https4 甚至在路由定义中那样简单地将信任库添加到组件的提示,即:
from(ENDPOINT_URI)
.setProperty(SecurityConstants.PASSWORD, constant(PASSWORD))
.setProperty(SecurityConstants.USERNAME, constant(USERNAME))
.to("cxf://" + SERVICE_URL + "?" +
"wsdlURL=" + WSDL_URL + "&" +
"serviceName=" + SERVICE_NAME + "&" +
"portName=" + PORT_NAME + "&" +
"dataFormat=CXF_MESSAGE&" +
"synchronous=true&" +
"defaultOperationName=" + DEFAULT_OPERATION_NAME)
.streamCaching();
我认为这一定是一个非常简单的问题,所以我仍然希望有一些巧妙的方法来简单地添加信任库(或者甚至接受任何证书,因为它与我们的用例无关)。如果有一种简单的编程方式,我会非常高兴。有人知道吗?
我通过将证书添加到 jre/lib/cacerts 中的 JVM 信任库解决了这个问题。这是可行的,因为我可以访问应用程序 运行 所在机器上的 JVM。这似乎是最简单的解决方案。
更新
如果有人对更合适的解决方案感兴趣:CxfEndpoint 提供了一种影响 HTTPConduit 及其 TLS 参数的方法。这是修改后的代码:
- 将 "cxfEndpointConfigurer=SageEndpointConfigurer" 添加到 cxf 端点参数
- 创建端点时 "SageEndpointConfigurer" 将使用 TypeConverters
解析
- 在context的TypeConverter Registry中添加一个TypeConverter,即直接在RouteBuilder中
getContext().getTypeConverterRegistry().addTypeConverter(CxfEndpointConfigurer.class, String.class, new SageEndpointConfigurerConverter());
配置 TLSParameters 并简单地 return 来自 TypeConverter
的 CxfEndpointConfigurer
private class SageEndpointConfigurerConverter extends TypeConverterSupport {
@Override
public <T> T convertTo(Class<T> type, Exchange exchange, Object value) throws TypeConversionException {
CxfEndpointConfigurer configurer = new CxfEndpointConfigurer() {
@Override
public void configure(AbstractWSDLBasedEndpointFactory factoryBean) {
// do nothing
}
@Override
public void configureClient(Client client) {
URLConnectionHTTPConduit conduit = (URLConnectionHTTPConduit) client.getConduit();
TLSClientParameters tlsParams = new TLSClientParameters();
tlsParams.setDisableCNCheck(true);
tlsParams.setTrustManagers(new TrustManager[]{new TrustAllTrustManager()});
conduit.setTlsClientParameters(tlsParams);
}
@Override
public void configureServer(Server server) {
//do nothing
}
};
return (T) configurer;
}
}
TrustAllManager 就是这样实现的
public class TrustAllTrustManager implements X509TrustManager {
private static Logger LOG = LoggerFactory.getLogger(TrustAllTrustManager.class);
@Override
public void checkClientTrusted(X509Certificate[] x509Certificates, String authType) throws CertificateException {
//do nothing, trust all certificates
logMessage(x509Certificates, authType);
}
@Override
public void checkServerTrusted(X509Certificate[] x509Certificates, String authType) throws CertificateException {
//do nothing, trust all certificates
logMessage(x509Certificates, authType);
}
@Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
private void logMessage(X509Certificate[] x509Certificates, String authType) {
StringBuilder message = new StringBuilder();
String lineSeparator = System.getProperty("line.separator");
message.append("Trusted following certificates for authentication type '").append(authType).append("'").append(lineSeparator);
for (X509Certificate certificate : x509Certificates) {
message.append(certificate).append(lineSeparator);
}
LOG.trace(message.toString());
}
}
我正在使用 Apache Camel CXF 作为生产者来调用 SOAP Web 服务。我不使用 Spring 配置,而是以编程方式执行所有操作(我是初学者,希望避免同时学习 Spring 和 Apache Camel)。 Web 服务使用带有自签名证书的 SSL。我将它添加到一个信任库中,并希望能够将它添加到 CxfEndpoint 中,就像我使用 https4:
所做的那样KeyStoreParameters ksp = new KeyStoreParameters();
ksp.setResource("src/main/resources/truststore.jks");
ksp.setPassword("...");
KeyManagersParameters kmp = new KeyManagersParameters();
kmp.setKeyStore(ksp);
kmp.setKeyPassword("...");
SSLContextParameters scp = new SSLContextParameters();
scp.setKeyManagers(kmp);
CamelContext context = new DefaultCamelContext();
context.addRoutes(routeBuilder);
HttpComponent httpComponent = context.getComponent("https4", HttpComponent.class);
httpComponent.setSslContextParameters(scp);
– 但这似乎不适用于 CxfComponent。我找到了很多关于使用 Spring 添加 TlsClientParameters 和配置 CxfEndpoint 的文档,例如:
这里
from(ENDPOINT_URI)
.setProperty(SecurityConstants.PASSWORD, constant(PASSWORD))
.setProperty(SecurityConstants.USERNAME, constant(USERNAME))
.to("cxf://" + SERVICE_URL + "?" +
"wsdlURL=" + WSDL_URL + "&" +
"serviceName=" + SERVICE_NAME + "&" +
"portName=" + PORT_NAME + "&" +
"dataFormat=CXF_MESSAGE&" +
"synchronous=true&" +
"defaultOperationName=" + DEFAULT_OPERATION_NAME)
.streamCaching();
我认为这一定是一个非常简单的问题,所以我仍然希望有一些巧妙的方法来简单地添加信任库(或者甚至接受任何证书,因为它与我们的用例无关)。如果有一种简单的编程方式,我会非常高兴。有人知道吗?
我通过将证书添加到 jre/lib/cacerts 中的 JVM 信任库解决了这个问题。这是可行的,因为我可以访问应用程序 运行 所在机器上的 JVM。这似乎是最简单的解决方案。
更新
如果有人对更合适的解决方案感兴趣:CxfEndpoint 提供了一种影响 HTTPConduit 及其 TLS 参数的方法。这是修改后的代码:
- 将 "cxfEndpointConfigurer=SageEndpointConfigurer" 添加到 cxf 端点参数
- 创建端点时 "SageEndpointConfigurer" 将使用 TypeConverters 解析
- 在context的TypeConverter Registry中添加一个TypeConverter,即直接在RouteBuilder中
getContext().getTypeConverterRegistry().addTypeConverter(CxfEndpointConfigurer.class, String.class, new SageEndpointConfigurerConverter());
配置 TLSParameters 并简单地 return 来自 TypeConverter
的 CxfEndpointConfigurerprivate class SageEndpointConfigurerConverter extends TypeConverterSupport { @Override public <T> T convertTo(Class<T> type, Exchange exchange, Object value) throws TypeConversionException { CxfEndpointConfigurer configurer = new CxfEndpointConfigurer() { @Override public void configure(AbstractWSDLBasedEndpointFactory factoryBean) { // do nothing } @Override public void configureClient(Client client) { URLConnectionHTTPConduit conduit = (URLConnectionHTTPConduit) client.getConduit(); TLSClientParameters tlsParams = new TLSClientParameters(); tlsParams.setDisableCNCheck(true); tlsParams.setTrustManagers(new TrustManager[]{new TrustAllTrustManager()}); conduit.setTlsClientParameters(tlsParams); } @Override public void configureServer(Server server) { //do nothing } }; return (T) configurer; } }
TrustAllManager 就是这样实现的
public class TrustAllTrustManager implements X509TrustManager { private static Logger LOG = LoggerFactory.getLogger(TrustAllTrustManager.class); @Override public void checkClientTrusted(X509Certificate[] x509Certificates, String authType) throws CertificateException { //do nothing, trust all certificates logMessage(x509Certificates, authType); } @Override public void checkServerTrusted(X509Certificate[] x509Certificates, String authType) throws CertificateException { //do nothing, trust all certificates logMessage(x509Certificates, authType); } @Override public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; } private void logMessage(X509Certificate[] x509Certificates, String authType) { StringBuilder message = new StringBuilder(); String lineSeparator = System.getProperty("line.separator"); message.append("Trusted following certificates for authentication type '").append(authType).append("'").append(lineSeparator); for (X509Certificate certificate : x509Certificates) { message.append(certificate).append(lineSeparator); } LOG.trace(message.toString()); } }