我使用以下代码在Oracle文档之后使用TLS和JMXMP创建自定义JMX服务器。它运行良好,我可以毫无问题地连接到服务器,但是我想添加" USER"和"密码"验证,但指定" password.properties"和#34; access.properties"没有用,JMX似乎忽略了这两个选项。有人可以说明配置USER和PASSWORD的正确方法并纠正这个问题吗?感谢
private JMXServiceURL url() {
final String url = String.format( "service:jmx:jmxmp://%s:%s", host(), port() );
try {
return new JMXServiceURL( url );
} catch( Throwable exception ) {
throw new RuntimeException( String.format( "Failed to create JMX Service URL: %s", url ), exception );
}
}
private Map<String, Object> env() {
final Map<String, Object> env = new LinkedHashMap<String, Object>();
try {
String keystore = "jmx.keystore";
char keystorepass[] = "12345678".toCharArray();
char keypassword[] = "12345678".toCharArray();
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(keystore), keystorepass);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, keypassword);
SSLContext ctx = SSLContext.getInstance("TLSv1");
ctx.init(kmf.getKeyManagers(), null, null);
SSLSocketFactory ssf = ctx.getSocketFactory();
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_NULL_MD5");
env.put("jmx.remote.x.password.file", "password.properties");
env.put("jmx.remote.x.access.file","access.properties");
} catch (Exception e) {
e.printStackTrace();
}
return env;
}
private MBeanServer server() {
return ManagementFactory.getPlatformMBeanServer();
}
private JMXConnectorServer connector() {
try {
ServerProvider.class.getName();
return JMXConnectorServerFactory.newJMXConnectorServer( url(), env(), server() );
}catch( Throwable exception ) {
throw new RuntimeException( "Failed to create JMX connector server factory", exception );
}
}
答案 0 :(得分:1)
我终于能够使用Oracle文档中的以下代码为JMXMP连接配置其他用户和密码
MBeanServer mbs = MBeanServerFactory.createMBeanServer();
Security.addProvider(new com.sun.jdmk.security.sasl.Provider());
HashMap env = new HashMap();
env.put("jmx.remote.profiles", "TLS SASL/PLAIN");
env.put("jmx.remote.sasl.callback.handler",
new PropertiesFileCallbackHandler("password.properties"));
env.put("jmx.remote.x.access.file",access.properties");
JMXServiceURL url = new JMXServiceURL("jmxmp", null, 5555);
JMXConnectorServer cs =
JMXConnectorServerFactory.newJMXConnectorServer(url,
env,
mbs);
cs.start();
我为密码验证实现了一个简单的callBackHandler
public final class PropertiesFileCallbackHandler
implements CallbackHandler {
private Properties pwDb;
/**
* Contents of files are in the Properties file format.
*
* @param pwFile name of file containing name/password
*/
public PropertiesFileCallbackHandler(String pwFile) throws IOException {
if (pwFile != null) {
File file = new File(pwFile);
if(file.exists()) {
pwDb = new Properties();
pwDb.load(new FileInputStream(file));
} else {
throw new IOException("File " + pwFile + " not found");
}
}
}
public void handle(Callback[] callbacks)
throws UnsupportedCallbackException {
AuthorizeCallback acb = null;
AuthenticateCallback aucb = null;
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof AuthorizeCallback) {
acb = (AuthorizeCallback) callbacks[i];
} else if (callbacks[i] instanceof AuthenticateCallback) {
aucb = (AuthenticateCallback)callbacks[i];
} else {
throw new UnsupportedCallbackException(callbacks[i]);
}
}
// Process retrieval of password; can get password if
// username is available
if (aucb != null) {
String username = aucb.getAuthenticationID();
String password = new String(aucb.getPassword());
String pw = pwDb.getProperty(username);
if (pw != null) {
if(pw.equals(password)){
aucb.setAuthenticated(true);
}
}
}
// Check for authorization
if (acb != null) {
String authid = acb.getAuthenticationID();
String authzid = acb.getAuthorizationID();
if (authid.equals(authzid)) {
// Self is always authorized
acb.setAuthorized(true);
}
}
}
}