ActiveMQ javax.net.ssl.sslhandshakeexception null 证书链

Posted

技术标签:

【中文标题】ActiveMQ javax.net.ssl.sslhandshakeexception null 证书链【英文标题】:ActiveMQ javax.net.ssl.sslhandshakeexception null cert chain 【发布时间】:2020-10-09 09:30:36 【问题描述】:

I used this link to create the self signed root CA certificate and the server key pair

Used this link to generate the client key pair using the previously generated root certificate

虽然这些链接用于为 MosquittoMQ 设置 SSL,而我的用例是用于 ActiveMQ,但我相信无论哪种情况,证书生成过程都是相同的。

我使用的客户端是 Java 客户端。 根据密钥库的要求,代理密钥库包含捆绑到 PKCS12 文件中的根证书和服务器公钥和私钥,代理信任库包含客户端的公钥。客户端密钥库包含捆绑到 PKCS12 文件中的客户端公钥和私钥,客户端信任库包含根证书。 Java 客户端使用端口 61714 连接到代理。通过以上配置的密钥库和信任库,我得到 null cert chain 异常。有人可以告诉我这是否是配置密钥和信任存储的正确方法吗?根证书和服务器证书是否应该链接而不是单独存在于代理密钥库中? 我对此很陌生,有点迷茫。

ActiveMQ 代理的传输连接器配置如下所示

    <managementContext>
            <managementContext createConnector="false"/>
</managementContext>
<sslContext> 
            <sslContext keyStore="file:$activemq.base/conf/broker.ks"
              keyStorePassword="changeit" trustStore="file:$activemq.base/conf/broker.ts"
              trustStorePassword="changeit"/> 
</sslContext>
<transportConnectors>
        <!-- DOS protection, limit concurrent connections to 1000 and frame size to 100MB -->
        <transportConnector name="openwire" uri="tcp://0.0.0.0:61616?maximumConnections=1000&amp;wireFormat.maxInactivityDuration=300000&amp;wireFormat.maxFrameSize=104857600&amp;jms.messagePrioritySupported=false"/>
        <transportConnector name="ssl" uri="ssl://0.0.0.0:61714?trace=true&amp;needClientAuth=true&amp;transport.enabledProtocols=TLSv1.2"/>
        <transportConnector name="amqp" uri="amqp://0.0.0.0:5672?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
        <transportConnector name="stomp" uri="stomp://0.0.0.0:61613?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
        <transportConnector name="mqtt" uri="mqtt://0.0.0.0:1883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
        <transportConnector name="mqtt+ssl" uri="mqtt+ssl://0.0.0.0:8883?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
        <transportConnector name="ws" uri="ws://0.0.0.0:61614?maximumConnections=1000&amp;wireFormat.maxFrameSize=104857600"/>
</transportConnectors>

Java 客户端上的application.properties 文件

# Embedded ActiveMQ Configuration
spring.activemq.in-memory=false
spring.activemq.pool.enabled=false
activemq.broker-url=tcp://localhost:61616
activemq.ssl-url=ssl://localhost:61714


# Spring JMS Settings
#spring.jms.pub-sub-domain=true

# Truststore used by client.
JMS_BROKER_TRUSTSTORE=E:\\apacheActiveMQ\\apache-activemq-5.13.0\\conf\\client.ts
JMS_BROKER_TRUSTSTORE_TYPE=JKS
JMS_BROKER_TRUSTSTORE_PASSWORD=changeit
# Keystore used by client.
JMS_BROKER_KEYSTORE=E:\\apacheActiveMQ\\apache-activemq- 5.13.0\\conf\\client.ks
JMS_BROKER_KEYSTORE_TYPE=JKS
JMS_BROKER_KEYSTORE_PASSWORD=changeit

处理在 Java 客户端上配置 ActiveMQ 连接工厂的文件

@Bean
public ActiveMQSslConnectionFactory activeMQSslConnectionFactory() 
    ActiveMQSslConnectionFactory connectionFactory = new ActiveMQSslConnectionFactory(sslUrl);
    try 
        connectionFactory.setTrustStore(pathToTrustStore);
        connectionFactory.setTrustStorePassword(truststorePassword);
        connectionFactory.setKeyStore(pathToKeystore);
        connectionFactory.setKeyStorePassword(keystorePassword);
     catch (Exception e) 
        System.out.println("Error");
    
    return connectionFactory;


/**
 * Initialise @link JmsTemplate as required
 */
@Bean
public JmsTemplate jmsTemplate() 
    JmsTemplate jmsTemplate = new JmsTemplate();
    jmsTemplate.setConnectionFactory(activeMQSslConnectionFactory());
    jmsTemplate.setExplicitQosEnabled(true);

    //setting PuSubDomain to true configures JmsTemplate to work with topics instead of queues
    jmsTemplate.setPubSubDomain(true);
    jmsTemplate.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
    return jmsTemplate;


/**
 * Initialise @link DefaultJmsListenerContainerFactory as required
 */
@Bean
public DefaultJmsListenerContainerFactory jmsListenerContainerFactory() 
    DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
    factory.setConnectionFactory(activeMQSslConnectionFactory());
    //setting PuSubDomain to true configures the DefaultJmsListenerContainerFactory to work with topics instead of queues
    factory.setPubSubDomain(true);
    return factory;

【问题讨论】:

我在您发布的配置中没有看到任何 SSL 上下文配置 嘿蒂姆,我已经编辑了帖子以包含更多信息。 【参考方案1】:

回答我自己的问题。 下面是keystore/truststore及其内容的映射

代理密钥库:捆绑到 PKCS12 文件中的服务器密钥对 代理信任库:根证书 客户端密钥库:绑定到 PKCS12 文件中的客户端密钥对 客户端信任库:根证书

这是正确的配置,现在一切正常。 不完全确定为什么关于为 MQTT 配置证书的内容很少。我查看了一堆 HTTPS 示例,了解到证书必须添加到密钥库和信任库中,如上所示。

【讨论】:

以上是关于ActiveMQ javax.net.ssl.sslhandshakeexception null 证书链的主要内容,如果未能解决你的问题,请参考以下文章

ActiveMQ知识概括

ActiveMQ知识概括

activemq连接过多导致变慢

为啥activemq有两个端口

ActiveMq入门实例

ActiveMQ入门实例