【问题标题】:Make Https request with the netty4-http component of Apache Camel使用 Apache Camel 的 netty4-http 组件发出 Https 请求
【发布时间】:2020-05-04 15:39:15
【问题描述】:

我使用 Apache Camel 公开了一个简单的 REST 服务,例如 Spring boot 微服务,它使用 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 错误。从日志中我读到请求以 HTTP 而不是 HTTPS 格式到达,我不明白为什么:

您对启用 SSL 的服务器端口使用纯 HTTP。而是使用 请使用 HTTPS 方案访问此 URL。

如果我使用 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 路径构建失败: sun.security.provider.certpath.SunCertPathBuilderException:无法 找到请求目标的有效认证路径

【问题讨论】:

    标签: ssl https apache-camel netty


    【解决方案1】:

    您可能需要configure a sslContextParameters object 才能使用configure the Netty component 进行SSL。

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

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

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

    Netty component(不是http)也有一个参数ssl=true。不知道Netty-http 是否也需要这样做。因此,您必须使用这些不同的参数进行一些测试。

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

    【讨论】:

    • 非常感谢。从该文档和其他文档报告时,我只是在修改以下代码,但现在我有点困惑。我更新了帖子
    【解决方案2】:

    已解决。缺少自签名证书所需的一些说明。 下面是完整的 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时设置的密码。

    我希望它会有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-10-15
      相关资源
      最近更新 更多