简体   繁体   English

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

[英]JMX with SSL without using system properties

I spent much working on adding support JMX into a enterprise application. 我花了很多有关添加支持JMX为企业应用程序的工作。 JMX should use SSL and client authentication by SQL. JMX应该使用SSL和通过SQL的客户端身份验证。 That´s not the problem. 那不是问题。 I`m using system properties to enable SSL. 我真的使用系统属性来启用SSL。 System properties are global to a JVM. 系统属性是全局的,JVM。 Especially in a large application, conflicts can quickly arise if alternate configuration methods aren't available. 尤其是在大型应用程序中,如果没有备用的配置方法,则可能会迅速产生冲突。

Especially in a large enterprise application, calls need to be made to different services that require different certificates, and especially with limitations around automatic certificate selection, there needs to be a way to hook into this through flexible code when required. 尤其是在大型企业应用程序,调用需要,需要不同的证书,尤其是周围自动选择证书的限制,需要有通过灵活的代码需要时,挂到这个方式不同的服务作出。 Unfortunately, JMX and RMI currently provide no such hooks, relying exclusively on system properties or the default socket factory. 不幸的是,JMX和RMI当前不提供此类挂钩,仅依赖于系统属性或默认的套接字工厂。

Is there any way to make JMX using SSL by not using system properties? 有没有什么办法让JMX使用SSL通过不使用系统属性?

Edit: 编辑:

Using SslRMIClientSocketFactory did not work. 使用的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 );

Exception: 例外:

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)

You can create your own RMIConnectorServer , and conditionally enable it for SSL. 您可以创建自己的RMIConnectorServer ,并有条件地为SSL启用它。 When constructing the server instance, the environment map can be loaded with defined RMIClientSocketFactory and RMIServerSocketFactory instances. 构造服务器实例时,可以使用定义的RMIClientSocketFactoryRMIServerSocketFactory实例加载环境映射。 To enable SSL, these factories can be set as configured SslRMIClientSocketFactory and SslRMIServerSocketFactory instances and you will have recreated the equivalent of the system props configured connector server. 要启用SSL,可以将这些工厂设置为已配置的SslRMIClientSocketFactorySslRMIServerSocketFactory实例,并且您将重新创建与系统props配置的连接器服务器等效的对象。 I have not done this with SSL, but it seems fairly well documented. 我尚未使用SSL进行此操作,但是它的文档似乎不错。

Solution: 解:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM