您的位置:首页 > 运维架构

使用SSL双向认证和JMXMP实现对系统状态的监控

2015-11-02 16:41 525 查看
在实际生产环境下,使用RMI实现JMX会受到来自防火墙的诸多限制,替代的方案就是使用JMXMP协议。核心代码实现如下:

JMX服务端:
final String protocol = "jmxmp";
final String host = "192.168.1.6";
final int port = 12345;
final String serverKeyStoreFile = appBase + "/config/jmxkey/server.keystore";
final String serverKeyStorePwd = "storepass";
final String serverKeyPwd = "keypass";
final String serverTrustKeyStoreFile = appBase + "/config/jmxkey/servertrust.keystore";
final String serverTrustKeyStorePwd = "truststorepass";

// 创建MBeanServer
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

// 创建并注册MBean
final String domain = "app";
final String className = AppInfo.class.getName();
final String name = domain + ":" + "name=" + className;
final ObjectName objectName = ObjectName.getInstance(name);
mbs.createMBean(className, objectName);

// 创建SSLSocketFactory
KeyStore serverKeyStore = KeyStore.getInstance("JKS");
serverKeyStore.load(new FileInputStream(serverKeyStoreFile),
serverKeyStorePwd.toCharArray());

KeyStore serverTrustKeyStore = KeyStore.getInstance("JKS");
serverTrustKeyStore.load(new FileInputStream(serverTrustKeyStoreFile),
serverTrustKeyStorePwd.toCharArray());

KeyManagerFactory kmf = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(serverKeyStore, serverKeyPwd.toCharArray());

TrustManagerFactory tmf = TrustManagerFactory
.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(serverTrustKeyStore);

SSLContext sslContext = SSLContext.getInstance("TLSv1");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
SSLSocketFactory ssf = sslContext.getSocketFactory();

// 创建JMX服务器
Map<String, Object> env = new HashMap<>();
env.put("jmx.remote.profiles", "TLS");
env.put("jmx.remote.tls.socket.factory", ssf);
env.put("jmx.remote.tls.enabled.protocols", "TLSv1");
env.put("jmx.remote.tls.enabled.cipher.suites",
"SSL_RSA_WITH_3DES_EDE_CBC_SHA");
JMXServiceURL url = new JMXServiceURL(protocol, host, port);
JMXConnectorServer cs = JMXConnectorServerFactory
.newJMXConnectorServer(url, env, mbs);
cs.start();


JMX客户端:
final String protocol = "jmxmp";
final String host = "192.168.1.6";
final int port = 12345;
final String clientKeyStoreFile = appBase + "/config/jmxkey/client.keystore";
final String clientKeyStorePwd = "storepass";
final String foxclientKeyPwd = "keypass";
final String clientTrustKeyStoreFile = appBase + "/config/jmxkey/clienttrust.keystore";
final String clientTrustKeyStorePwd = "truststorepass";

// 创建SSLSocketFactory
KeyStore clientKeyStore = KeyStore.getInstance("JKS");
clientKeyStore.load(new FileInputStream(clientKeyStoreFile), clientKeyStorePwd.toCharArray());

KeyStore clientTrustKeyStore = KeyStore.getInstance("JKS");
clientTrustKeyStore.load(new FileInputStream(clientTrustKeyStoreFile), clientTrustKeyStorePwd.toCharArray());

KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(clientKeyStore, foxclientKeyPwd.toCharArray());

TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(clientTrustKeyStore);

SSLContext sslContext = SSLContext.getInstance("TLSv1");
sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
SSLSocketFactory ssf = sslContext.getSocketFactory();

// 创建JMX客户端
HashMap<String, Object> env = new HashMap<>();
env.put("jmx.remote.profiles", "TLS");
env.put("jmx.remote.tls.socket.factory", ssf);
env.put("jmx.remote.tls.enabled.protocols", "TLSv1");
env.put("jmx.remote.tls.enabled.cipher.suites",
"SSL_RSA_WITH_3DES_EDE_CBC_SHA");

JMXServiceURL url = new JMXServiceURL(protocol, host, port);
JMXConnector jmxc = JMXConnectorFactory.connect(url, env);
MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();

// 获取所有的域
final String domains[] = mbsc.getDomains();
for (int i = 0; i < domains.length; i++)
{
System.out.println("Domain[" + i + "] = " + domains[i]);
}

// 调用方法
final String domain = "app";
final String className = AppInfo.class.getName();
final String name = domain + ":" + "name=" + className;
final ObjectName objectName = ObjectName.getInstance(name);
AppInfoMXBean appInfo = JMX.newMBeanProxy(
mbsc, objectName, AppInfoMXBean.class);
System.out.println(appInfo.getAppName());
System.out.println(appInfo.getAppVersion());

jmxc.close();


keystore和trustkeystore生成
# 生成服务端keystore
keytool -genkey -alias server -keyalg rsa -keysize 1024 -sigalg sha256withrsa -keypass keypass -keystore E:\app\config\jmxkey\server.keystore -storepass storepass

# 生成客户端keystone
keytool -genkey -alias client -keyalg rsa -keysize 1024 -sigalg sha256withrsa -keypass keypass -keystore E:\app\config\jmxkey\client.keystore -storepass storepass

# 导出服务端证书
keytool -export -alias server -keystore E:\app\config\jmxkey\server.keystore -storepass storepass -file E:\app\config\jmxkey\server.cer

# 导出客户端证书
keytool -export -alias client -keystore E:\app\config\jmxkey\client.keystore -storepass storepass -file E:\app\config\jmxkey\client.cer

# 创建服务端truststore并导入客户端证书
keytool -import -alias client -keystore E:\app\config\jmxkey\servertrust.keystore -storepass truststorepass -file E:\app\config\jmxkey\client.cer

# 创建客户端truststore并导入服务端证书
keytool -import -alias server -keystore E:\app\config\jmxkey\clienttrust.keystore -storepass truststorepass -file E:\app\config\jmxkey\server.cer


参考文献:
《jmx rmi 穿越防火墙问题及jmxmp的替代方案》 http://blog.csdn.net/yangyan19870319/article/details/7244403
《11.4.3 TLS Socket Factory》 http://docs.oracle.com/cd/E19698-01/816-7609/6mdjrf86r/index.html
《Java-JSSE-SSL/TLS编程代码实例-双向认证》 http://blog.csdn.net/fw0124/article/details/41013333
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  JMX