使用相同的连接环境连接到启用SSL和禁用SSL的JMX远程代理

时间:2019-01-18 10:34:16

标签: java ssl jmx

我有一个程序,该程序监视来自JMX远程代理的流程性能数据。

其中一些远程代理已配置为使用SSL,并将JVM参数com.sun.management.jmxremote.sslcom.sun.management.jmxremote.registry.ssl设置为true。其他的不受SSL保护,请将这些JVM参数设置为false。

我使用JMXConnector通过以下方法连接到这些远程代理:

private JMXConnector setUpConnection(String server, int jmxPort) {

    try {

        Registry r = LocateRegistry.getRegistry(server, jmxPort);

        HashMap<String, Object> env = new HashMap<String, Object>();

        String[] credentials = {"username", "password"};
        env.put(JMXConnector.CREDENTIALS, credentials);
        env.put("com.sun.jndi.rmi.factory.socket", new SslRMIClientSocketFactory());  // uncomment if needed


                JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://" + server + ":" + jmxPort + "/jmxrmi");
        return JMXConnectorFactory.newJMXConnector(url, env);

    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;

}

此方法能够连接到我受SSL保护的远程代理,但不能连接到不使用SSL的远程代理。对于后一种情况,我收到的错误消息是:

java.io.IOException: Failed to retrieve RMIServer stub: javax.naming.CommunicationException [Root exception is java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: 
    javax.net.ssl.SSLHandshakeException: Remote host closed connection during handshake]

如果我删除以下行:

env.put("com.sun.jndi.rmi.factory.socket", new SslRMIClientSocketFactory());

然后发生相反的情况,我现在可以连接到未配置为使用SSL的远程代理,但无法连接到SSL远程代理。在这种情况下,我为配置了SSL的远程代理收到的错误消息是:

java.io.IOException: Failed to retrieve RMIServer stub: javax.naming.CommunicationException [Root exception is java.rmi.ConnectIOException: non-JRMP server at remote endpoint]

如果我没有将JVM参数com.sun.management.jmxremote.registry.ssl设置为true,那么我可以在忽略时连接到所有远程代理:

env.put("com.sun.jndi.rmi.factory.socket", new SslRMIClientSocketFactory());

但是不能将此属性设置为false。

我想不惜一切代价避免使用两种不同的连接环境,一种用于SSL远程代理,另一种用于非SSL远程代理。我也不能将所有远程代理迁移到配置SSL。

1 个答案:

答案 0 :(得分:2)

我们的一个项目,我们使用下面的代码片段来获取JMXConnection。

private String provider = "";
private String jvmPort = "";
private JMXServiceURL jmxService = null;
private JMXConnector jmxConnector = null;
private RMIConnector rmiConnector = null;
private MBeanServerConnection beanServerConn = null;
.........

public boolean connectToJVM(String jvmURL, String user, String pass)
{
    boolean flag = false;
    beanServerConn = null ;  
    try
    {
        jmxService = new JMXServiceURL(jvmURL);
        Map environment = new HashMap();
        int jmxconnect_timeout = 30000;
        environment.put("jmx.remote.protocol.provider.pkgs",provider);
        if (jmxconnect_timeout > 0) {
            environment.put("jmx.remote.x.request.waiting.timeout", Long.toString(jmxconnect_timeout));
        }
        boolean registrySSL = false;

        if(user.equalsIgnoreCase("none")|| (pass.equalsIgnoreCase("none")))
        {
            try
            {
                jmxConnector = JMXConnectorFactory.connect(jmxService,environment);
            }
            catch(IOException ioe)
            {
                registrySSL = true;
            }
        }
        else
        {
            String [] credentials={user,pass};
            environment.put(JMXConnector.CREDENTIALS, credentials);
            try
            {
                jmxConnector = JMXConnectorFactory.connect(jmxService,environment);
            }
            catch(IOException ioe)
            {
                registrySSL = true;
            }
        }

        if(registrySSL)
        {
            /*
                This if block runs when the "management.properties" file contains 
                com.sun.management.jmxremote.registry.ssl=true

                This block of code is applicable both JDK5.0 & 6.0

                Only for JDK6.0
                ===============
                    environment.put("com.sun.jndi.rmi.factory.socket", new SslRMIClientSocketFactory());
                    beanServerConn = jmxConnector.getMBeanServerConnection();
            */

            try {
                MySslRMIClientSocketFactory csf = new MySslRMIClientSocketFactory(targetHost, Integer.parseInt(jvmPort), (int)jmxconnect_timeout);
                Registry registry = LocateRegistry.getRegistry(targetHost, Integer.parseInt(jvmPort), csf);
                RMIServer stub = (RMIServer) registry.lookup(jndiName);
                rmiConnector = new RMIConnector(stub, environment);
                rmiConnector.connect(environment);
                beanServerConn = rmiConnector.getMBeanServerConnection();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        else{
            beanServerConn = jmxConnector.getMBeanServerConnection();
        }

        if(beanServerConn == null)
        {
            System.out.println("Connection to JVM is not established for url : " + url);
            return false;
        }
        else
        {
            flag = true;
        }
    }
    catch(Exception ex)
    {
        System.out.println("Connection to JVM is not established for url : " + url);
        //ex.printStackTrace();
        return false;
    }
    return flag;
}