当前位置: 首页 > 知识库问答 >
问题:

Apache Camel CXF:以编程方式添加TlsClientParameters

洪博艺
2023-03-14

我使用Apache Camel CXF作为生产者来调用SOAP Webservice。我不使用Spring配置,而是以编程方式完成所有工作(我是初学者,希望防止同时学习Spring和Apache Camel)。Webservice使用带有自签名证书的SSL。我将其添加到信任库中,并希望能够将其添加到CxfEndpoint,就像我使用http 4所做的那样:

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 的文档,例如:apache camel cxf https 不起作用,这里使用 CXF 和 Camel 调用安全 Web 服务。但是,我没有找到任何关于如何简单地向组件添加信任库的提示,就像我对 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();

我认为这一定是一个非常简单的问题,所以我仍然希望有一些巧妙的方法可以简单地添加信任库(甚至接受任何证书,因为它与我们的用例并不真正相关)。如果有一个简单的程序化方式,我会很高兴。有人知道吗?

共有1个答案

裴昕
2023-03-14

我通过将证书添加到jre/lib/cacert中的JVM信任库来解决这个问题。这是可行的,因为我可以访问运行应用程序的机器上的JVM。这似乎是最简单的解决方案。

更新

如果有人对更合适的解决方案感兴趣:CxfEndpoint提供了一种影响HTTPConduct及其TLS参数的方法。这是修订后的代码:

>

  • 将“cxfEndpointConfigurer=SageEndpointConfigurer”添加到cxfendpoint参数
  • 创建endpoint时,将使用TypeConverters解析“SageEndpointConfigurer”
  • 将TypeConverter添加到上下文的TypeConverter注册表中,即直接在RouteBuildergetContext().getTypeConverterRegistry().addTypeConverter(CxfEndpointConfigurer.class,String.class,newSageEndpointConfigurerConverter())中
  • 配置TLSParameters,只需从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());
    }
    }
    

  •  类似资料:
    • 我正在尝试在Android上添加Wifi网络,我想知道如何连接到不广播其SSID的Wifi网络(它是否有空SSID或带有\0s的清晰SSID)。 这是我目前用于广播其SSID的Wifi网络的内容:

    • 我有一个模型,其中有一个@列(nullable=false)注释HiberNate和所有字段有nullable=false,我想以编程方式添加一些新的注释,如@NotNull和@ApiModelProperty(必需=true)-用于招摇过市。 所以,我希望能够从我的应用程序的模型中解析所有字段,获得现有的注释,并在此基础上添加新的注释。这能做到吗? 更新:问题是每次添加一个新字段,如果它不能为空

    • 我正在使用SpringDoc,并试图以编程方式向OpenApi添加一个模式,但没有成功。 mySchema的描述没有添加到我在生成的YAML文件中看到的模式列表中,如果我试图引用它:

    • 问题内容: 我想在头部分中以编程方式添加StyleSheets,但是我看到的示例之一似乎需要多行代码才能仅添加一个样式表,即使我可能需要很多: 示例代码: 我也使用方法,但是它也不起作用。对象null抛出了错误。 我也使用了和东西,但是它们抛出了文字错误,这是我认为的常见错误。 我使用此代码: 起初它起作用,但是当我更改页面时,它停止工作。 我正在使用“母版页”,并且正在文件中编写这些代码,也有人

    • 问题内容: 我正在尝试使用导航栏(“后退”按钮,标题等)和选项卡栏(底部的工具栏)制作一个应用程序。我使用的是子视图,因此不必担心状态栏,导航栏,标签栏的高度等问题。但是我认为这给我带来了麻烦,因为我似乎无法弄清楚如何设置导航栏和标签栏。 这就是我所拥有的。我究竟做错了什么? AppDelegate.h AppDelegate.m ViewController.h ViewController.m

    • 问题内容: 如何以编程方式添加一个单击按钮即可执行操作的按钮?将使用什么代码? 我习惯在情节提要中添加一个按钮,然后从那里运行IBAction。 问题答案: 在SpriteKit中添加按钮并响应其点击并不像在UIKit中那样容易。基本上,您需要创建某种类型的对象,以绘制您的按钮,然后检查场景中记录的触摸是否在该节点的范围内。 一个非常简单的场景,中心只有一个红色矩形作为按钮,看起来像这样: 如果您