You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在JMX应用中配置SSL证书连接ActiveMQ Artemis?

配置JMX连接ActiveMQ Artemis的SSL证书

问题背景

已完成ActiveMQ Artemis broker端的SSL配置,现有JMX连接代码未启用SSL,需修改代码引入密钥库以建立SSL连接。

Broker端SSL配置(broker.xml)

<acceptor name="main-connector">tcp://localhost:61617?tcpSendBufferSize=1048576;amqpMinLargeMessageSize=102400;tcpReceiveBufferSize=1048576;sslEnabled=true;keyStorePath=keystore_server.jks;trustStorePath=truststore_server.jks;keyStorePassword=qwerty;trustStorePassword=qwerty;needClientAuth=true;protocols=CORE,AMQP,STOMP,HORNETQ,MQTT,OPENWIRE;useEpoll=true;enabledCipherSuites=TLS_AES_256_GCM_SHA384,TLS_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA;enabledProtocols=TLSv1.3,TLSv1.2</acceptor>

Broker文件夹结构

Broker文件夹结构

当前未启用SSL的JMX连接代码

public static MBeanServerConnection connectBroker(String brokerUrl, String login, String password) {
    MBeanServerConnection mBeanServerConnection = null;
    try {
        Map<String, String[]> env = new HashMap();
        String[] creds = {login, password};
        env.put(JMXConnector.CREDENTIALS, creds);
        JMXConnector connector = JMXConnectorFactory.connect(new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + brokerUrl + "/jmxrmi"), env);
        mBeanServerConnection = connector.getMBeanServerConnection();
        DialogsAlert.brokerJmxRmiConnectionSuccess.showAndWait();
        LOGGER.log(Level.INFO,"success" + brokerUrl);
    } catch (Exception e) {
        LOGGER.log(Level.WARNING,"fail", e);
    }
    return mBeanServerConnection;
}

解决方案

由于你的broker配置了needClientAuth=true,客户端必须提供合法证书才能建立SSL连接,以下是两种可行的配置方式:

方式一:系统属性快速配置

直接在代码中设置JVM系统属性,指定客户端密钥库、信任库及密码,操作简单:

public static MBeanServerConnection connectBroker(String brokerUrl, String login, String password) {
    MBeanServerConnection mBeanServerConnection = null;
    try {
        // 配置SSL核心属性
        System.setProperty("javax.net.ssl.keyStore", "path/to/client_keystore.jks"); // 客户端密钥库路径
        System.setProperty("javax.net.ssl.keyStorePassword", "qwerty"); // 客户端密钥库密码
        System.setProperty("javax.net.ssl.trustStore", "path/to/client_truststore.jks"); // 客户端信任库路径,需包含broker证书
        System.setProperty("javax.net.ssl.trustStorePassword", "qwerty"); // 客户端信任库密码
        // 可选:指定SSL协议,匹配broker的enabledProtocols配置
        System.setProperty("jdk.tls.client.protocols", "TLSv1.3,TLSv1.2");

        Map<String, Object> env = new HashMap<>();
        String[] creds = {login, password};
        env.put(JMXConnector.CREDENTIALS, creds);
        // 启用JMX SSL
        env.put("jmx.remote.ssl.enabled", "true");

        JMXConnector connector = JMXConnectorFactory.connect(
                new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + brokerUrl + "/jmxrmi"), 
                env);
        mBeanServerConnection = connector.getMBeanServerConnection();
        DialogsAlert.brokerJmxRmiConnectionSuccess.showAndWait();
        LOGGER.log(Level.INFO,"success" + brokerUrl);
    } catch (Exception e) {
        LOGGER.log(Level.WARNING,"fail", e);
    }
    return mBeanServerConnection;
}

注意:客户端密钥库需包含被broker信任库(truststore_server.jks)认可的客户端证书;客户端信任库需包含broker的证书(可从broker的keystore_server.jks导出后导入)。

方式二:自定义SSLContext(灵活可控)

如果需要精细控制SSL配置,可手动创建SSLContext并注入到JMX连接环境:

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import java.io.FileInputStream;
import java.security.KeyStore;

public static MBeanServerConnection connectBroker(String brokerUrl, String login, String password) {
    MBeanServerConnection mBeanServerConnection = null;
    try {
        // 加载客户端密钥库
        KeyStore keyStore = KeyStore.getInstance("JKS");
        try (FileInputStream keyStoreStream = new FileInputStream("path/to/client_keystore.jks")) {
            keyStore.load(keyStoreStream, "qwerty".toCharArray());
        }
        KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
        keyManagerFactory.init(keyStore, "qwerty".toCharArray());

        // 加载客户端信任库
        KeyStore trustStore = KeyStore.getInstance("JKS");
        try (FileInputStream trustStoreStream = new FileInputStream("path/to/client_truststore.jks")) {
            trustStore.load(trustStoreStream, "qwerty".toCharArray());
        }
        TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init(trustStore);

        // 创建匹配broker协议的SSLContext
        SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
        sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);

        Map<String, Object> env = new HashMap<>();
        String[] creds = {login, password};
        env.put(JMXConnector.CREDENTIALS, creds);
        env.put("jmx.remote.ssl.enabled", "true");
        env.put("jmx.remote.ssl.context", sslContext);
        // 指定RMI SSL协议提供者
        env.put(JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, "com.sun.jmx.remote.protocol");

        JMXConnector connector = JMXConnectorFactory.connect(
                new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + brokerUrl + "/jmxrmi"), 
                env);
        mBeanServerConnection = connector.getMBeanServerConnection();
        DialogsAlert.brokerJmxRmiConnectionSuccess.showAndWait();
        LOGGER.log(Level.INFO,"success" + brokerUrl);
    } catch (Exception e) {
        LOGGER.log(Level.WARNING,"fail", e);
    }
    return mBeanServerConnection;
}

关键注意事项

  1. 客户端密钥库必须包含客户端证书,且该证书已被broker的truststore_server.jks信任(可通过将客户端证书导入broker信任库实现)。
  2. 客户端信任库必须包含broker的证书(可从broker的keystore_server.jks导出证书后导入客户端信任库)。
  3. 确保客户端配置的SSL协议、加密套件与broker的enabledProtocols、enabledCipherSuites一致,避免握手失败。

内容的提问来源于stack exchange,提问作者user21871375

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 00:07:04