不使用系统属性的带 SSL 的 JMX

JMX with SSL without using system properties

我花了很多时间将 JMX 支持添加到企业应用程序中。 JMX 应该使用 SQL 的 SSL 和客户端身份验证。那不是问题所在。 我正在使用系统属性来启用 SSL。 系统属性对于 JVM 是全局的。特别是在大型应用程序中,如果备用配置方法不可用,很快就会出现冲突。

特别是在大型企业应用程序中,需要调用需要不同证书的不同服务,尤其是在自动证书选择方面存在限制,需要有一种方法可以在需要时通过灵活的代码挂钩。 不幸的是,JMX 和 RMI 目前没有提供这样的钩子,完全依赖于系统属性或默认套接字工厂。

有没有什么方法可以在不使用系统属性的情况下使 JMX 使用 SSL?

编辑:

使用 SslRMIClientSocketFactory 无效。

//          System.setProperty( "java.rmi.server.randomIDs", "true" );
//          System.setProperty( "javax.net.ssl.keyStore", keystore );
//          System.setProperty( "javax.net.ssl.keyStorePassword",
//              "password" );

          // SSL-based RMI socket factories.
          SslRMIClientSocketFactory csf = new SslRMIClientSocketFactory();
          SslRMIServerSocketFactory ssf = new SslRMIServerSocketFactory();
          map.put( RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, csf );
          map.put( RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, ssf );

异常:

java.rmi.ConnectIOException: error during JRMP connection establishment; nested exception is: 
    javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
    at sun.rmi.transport.tcp.TCPChannel.createConnection(TCPChannel.java:304)

您可以创建自己的 RMIConnectorServer, and conditionally enable it for SSL. When constructing the server instance, the environment map can be loaded with defined RMIClientSocketFactory and RMIServerSocketFactory instances. To enable SSL, these factories can be set as configured SslRMIClientSocketFactory and SslRMIServerSocketFactory 实例,并且您将重新创建等效于系统道具配置的连接器服务器。我没有使用 SSL 完成此操作,但它似乎有据可查。

解决方案:

SslRMIClientSocketFactory csf = new SslRMIClientSocketFactory();
    SslRMIServerSocketFactory ssf = createSslRMIServerSocketFactory(null,null,false);
    map.put( RMIConnectorServer.RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE, csf );
    map.put( RMIConnectorServer.RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE, ssf );    

....

private static SslRMIServerSocketFactory createSslRMIServerSocketFactory(
          String[] enabledCipherSuites, String[] enabledProtocols,
          boolean sslNeedClientAuth )
      {
          try
          {
            // Load the SSL keystore properties from the config file
            String keyStore =  "KeyStore.jks";
            String keyStorePassword = "pass";
            String trustStore = "truststore";
            String trustStorePassword = "pass";

            char[] keyStorePasswd = null;
            if ( keyStorePassword.length() != 0 )
            {
              keyStorePasswd = keyStorePassword.toCharArray();
            }

            char[] trustStorePasswd = null;
            if ( trustStorePassword.length() != 0 )
            {
              trustStorePasswd = trustStorePassword.toCharArray();
            }

            KeyStore ks = null;
            if ( keyStore != null )
            {
              ks = KeyStore.getInstance( KeyStore.getDefaultType() );
              FileInputStream ksfis = new FileInputStream( keyStore );
              try
              {
                ks.load( ksfis, keyStorePasswd );
              }
              finally
              {
                ksfis.close();
              }
            }
            KeyManagerFactory kmf = KeyManagerFactory.getInstance( KeyManagerFactory
                .getDefaultAlgorithm() );
            kmf.init( ks, keyStorePasswd );

            KeyStore ts = null;
            if ( trustStore != null )
            {
              ts = KeyStore.getInstance( KeyStore.getDefaultType() );
              FileInputStream tsfis = new FileInputStream( trustStore );
              try
              {
                ts.load( tsfis, trustStorePasswd );
              }
              finally
              {
                tsfis.close();
              }
            }
            TrustManagerFactory tmf = TrustManagerFactory.getInstance( TrustManagerFactory
                .getDefaultAlgorithm() );
            tmf.init( (KeyStore) ts );

            SSLContext ctx = SSLContext.getInstance( "SSL" );
            ctx.init( kmf.getKeyManagers(), tmf.getTrustManagers(), null );

            return new SslRMIServerSocketFactory ( ctx, enabledCipherSuites, enabledProtocols,
                sslNeedClientAuth );
          }
          catch ( Exception e )
          {
            Logger.getGlobal().log( Level.SEVERE, e.getMessage() );
            return null;
          }
        }