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

时间:2016-04-20 06:53:11

标签: java ssl rmi jmx keystore

我花了很多精力将支持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)

2 个答案:

答案 0 :(得分:0)

您可以创建自己的RMIConnectorServer,并有条件地为SSL启用它。构建服务器实例时,可以使用已定义的RMIClientSocketFactoryRMIServerSocketFactory实例加载环境映射。要启用SSL,可以将这些工厂设置为已配置的SslRMIClientSocketFactorySslRMIServerSocketFactory实例,并且您将重新创建系统道具配置的连接器服务器的等效项。我没有用SSL做过这件事,但似乎记录得很清楚。

答案 1 :(得分:0)

解决方案:

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;
          }
        }