使用 Apache Camel 的 netty4-http 组件发出 Https 请求

Make Https request with the netty4-http component of Apache Camel

我使用 Apache Camel 公开了一个简单的 REST 服务,例如 Spring 启动微服务,它使用 netty4-http 组件创建对 https 服务的请求。

public class RoutingTest extends RouteBuilder {

    @Override
    public void configure() throws Exception {

        restConfiguration()
            .host("localhost")
            .port("8080");

        rest().post("test") 
        .route()
            .setBody(constant("message=Hello"))
            .setHeader(Exchange.HTTP_METHOD, constant(HttpMethod.POST))
            .setHeader(Exchange.CONTENT_TYPE, constant("application/x-www-form-urlencoded"))
            .to("netty4-http:https://localhost/service/test");
    }
}

当我调用 http://localhost:8080/test 时,我在路由调用 https://localhost/service/test 时收到 400 Bad Request 错误 service.From 我读到的日志显示请求以 HTTP 而不是 HTTPS 格式到达,我没有'不明白为什么:

You're speaking plain HTTP to an SSL-enabled server port. Instead use the HTTPS scheme to access this URL, please.

如果我使用 Postman 调用服务 https://localhost/service/test,它会正常工作。

SSL 配置了自签名证书。

如何使用 apache camel 中的 netty 组件创建正确的 https 请求?文档只建议更换协议,顶多有几个选项是行不通的。

更新(已解决,见下文)

我是这样更新调用的

.to("netty4-http:https://localhost/dpm/idp/oauth/token?ssl=true&sslContextParameters=#sslContextParameters");

ssl = true 参数是必需的,我还为 SSLContextParameters 配置了 bean,如下所示:

@Bean(name = "sslContextParameters")
public static SSLContextParameters sslParameters() throws KeyManagementException, GeneralSecurityException, IOException {

    KeyStoreParameters ksp = new KeyStoreParameters();
    ksp.setResource("C:/myfolder/test.jks");

    KeyManagersParameters kmp = new KeyManagersParameters();
    kmp.setKeyStore(ksp);
    kmp.setKeyPassword("jskPassword");      

    SSLContextParameters scp = new SSLContextParameters();
    scp.setKeyManagers(kmp);

    SSLContextBuilder builder = new SSLContextBuilder();
    builder.loadTrustMaterial(new TrustSelfSignedStrategy());
    SSLContext sslcontext = builder.build();
    scp.createSSLContext().setDefault(sslcontext);

    return scp;
}

我正在与已弃用的 类 作斗争。为了进行测试,我只弃用了一种方法,因为我应该使用继承。

如果我理解正确,我必须从我的自签名证书(.crt 和 .key 文件)开始为信任区生成一个 JKS 文件。完成后,我添加了 KeyStoreParameters 和密码的说明。

差不多解决了,但是现在执行

的时候出现这个错误

PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

您可能需要 configure a sslContextParameters object that you can use to configure the Netty component SSL。

我不确定参数名称。文档说 sslContextParameters,但我认为是 sslContextParametersRef

.to("netty4-http:https://localhost/service/test?sslContextParametersRef=#sslConfig");

#sslConfig表示Camel可以从注册表中获取标识符为sslConfig的对象。因此,例如 Spring 这将是一个 Spring 托管 Bean,ID 为 sslConfig.

Netty component (not http) also has a parameter ssl=true. No idea if this is also needed for Netty-http。因此,您将不得不使用这些不同的参数进行一些测试。

顺便说一下,Netty 组件的文档有 an SSL example with context parameter configuration 等等。看看吧。

已解决。缺少自签名证书所需的一些说明。 下面是完整的bean。

@Bean(name = "sslContextParameters")
public static SSLContextParameters sslParameters() throws KeyManagementException, GeneralSecurityException, IOException {

    KeyStoreParameters ksp = new KeyStoreParameters();
    ksp.setResource("C:/myfolder/test.jks");
    ksp.setPassword("jskPassword");

    KeyManagersParameters kmp = new KeyManagersParameters();
    kmp.setKeyStore(ksp);
    kmp.setKeyPassword("jskPassword");

    SSLContextParameters scp = new SSLContextParameters();
    scp.setKeyManagers(kmp);

    SSLContextBuilder builder = new SSLContextBuilder();
    builder.loadTrustMaterial(null, new TrustSelfSignedStrategy());
    SSLContext sslcontext = builder.build();
    scp.createSSLContext().setDefault(sslcontext);

    // Necessary for the the self-signed server certificate
    TrustManagersParameters tmp = new TrustManagersParameters();
    tmp.setKeyStore(ksp);
    scp.setTrustManagers(tmp);

    return scp;
}

至于 test.jks 文件,我使用 keytool 创建了它,该工具随 JDK 一起提供,用于管理证书(创建、导出和导入)。 在我已经使用 OpenSSL 创建证书的情况下,我只需要创建要导入的 JKS (Java Keystore) 文件。因为需要在 P12 文件中转换证书(它应该是一个存档),最后在 JKS.

在操作过程中,您将被要求输入两个文件的密码

- openssl pkcs12 -export -in test.crt -inkey test.key -out test.p12
- keytool -importkeystore -srckeystore test.p12 -destkeystore test.jks -srcstoretype pkcs12
- keytool -importkeystore -srckeystore test.jks -destkeystore test.jks -deststoretype pkcs12

这里test是我的证书文件名。最后一个操作不是强制性的,但 keytool 本身建议将 JKS 格式(如果我理解正确的话是专有格式)迁移到更常见的 PKCS12 格式。

代码中的值jskPassword是我在创建keystore时设置的密码

希望对你有所帮助。