如何使JMX自定义身份validation工作?

我在JMX上使用密码和基于访问文件的身份validation。 构建我的JMXConnectorServer时,我使用属性名称,它工作正常。

Map env = new HashMap(); env.put(ApplicationProperties.JMX_PWD_FILE_PROP, pwdFile); env.put(ApplicationProperties.JMX_ACCESS_FILE_PROP, accFile); connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(jmxServiceURL, env, mBeanServer); 

但是,现在我想使用自定义身份validation器,我实现了自己的LoginModule,在密码文件中有一个加密密码。 因此,想法是在密码文件中具有加密密码和纯文本用户名。

 public class ABCDJMXLoginModule implements LoginModule { private CallbackHandler callbackHandler; private Subject subject; private String u_username; private String u_password; private JMXPrincipal user; private Properties userCredentials; private String passwordFile; private String f_username; private String f_password; private static final Logger logger = LoggerFactory.getLogger(ABCDJMXLoginModule.class); public boolean abort() throws LoginException { // TODO Auto-generated method stub return false; } public boolean commit() throws LoginException { // TODO Auto-generated method stub return true; } public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) { this.subject = subject; this.callbackHandler = callbackHandler; } public boolean login() throws LoginException { try { attemptLogin(); loadPasswordFile(); } catch (Exception e) { logger.info("Exception, e"); } if (u_username == null || u_password == null) { throw new LoginException("Either no username or no password specified"); } logger.info("Password from user and file : " + u_password + " :: " + f_password); if (u_password.equals(f_password)) { return true; } return false; } public boolean logout() throws LoginException { // TODO Auto-generated method stub return true; } private void attemptLogin() throws LoginException { Callback[] callbacks = new Callback[2]; callbacks[0] = new NameCallback("u_username"); callbacks[1] = new PasswordCallback("u_password", false); try { callbackHandler.handle(callbacks); } catch (IOException e) { logger.error("IOException", e); } catch (UnsupportedCallbackException e) { logger.error("UnsupportedCallbackException", e); } u_username = ((NameCallback) callbacks[0]).getName(); user = new JMXPrincipal(u_username); char[] tmpPassword = ((PasswordCallback) callbacks[1]).getPassword(); u_password = tmpPassword.toString(); logger.info("UserName : " + u_username); logger.info("Password : " + u_password); System.arraycopy(tmpPassword, 0, u_password, 0, tmpPassword.length); ((PasswordCallback) callbacks[1]).clearPassword(); } private void loadPasswordFile() throws IOException { FileInputStream fis = null; passwordFile = "c:\\abcd.jmx.enc.password.file"; try { fis = new FileInputStream(passwordFile); } catch (SecurityException e) { logger.error("Security Exception", e); } BufferedInputStream bis = new BufferedInputStream(fis); userCredentials = new Properties(); userCredentials.load(bis); bis.close(); f_username = u_username; f_password = (String) userCredentials.get(f_username); logger.info("UserName before Decrypt : " + f_username); logger.info("Password from file before Decrypt : " + f_password); // decrypt the password from file and later compare it with user password from JConsole if (f_password != null) f_password = Cryptography.decrypt(f_password); logger.info("Password from file after Decrypt : " + f_password); } } 

当我使用以下代码并尝试通过JConsole连接时没有任何反应。

 Map env = new HashMap(); env.put(ApplicationProperties.JMX_PWD_FILE_PROP, pwdFile); env.put(ApplicationProperties.JMX_ACCESS_FILE_PROP, accFile); env.put("jmx.remote.x.login.config", "com.splwg.ejb.service.management.ABCDJMXLoginModule"); connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(jmxServiceURL, env, mBeanServer); 

关于为什么会这样的想法? 当然,我也没有进入ABCDJMXLoginModule类 – 我有一些打印语句,没有打印出来。 任何想法和解决方案都表示赞赏。 我也尝试使用属性“com.sun.management.jmxremote.login.config”。 我期待在环境中提及属性并将其传递给JMXCOnnectorServer会做所有的伎俩。

我错过了什么吗?

 env.put("jmx.remote.x.login.config", "com.splwg.ejb.service.management.ABCDJMXLoginModule"); 

jmx.remote.x.login.config属性用于设置上下文名称,而不是LoginModule类名。

相反或者放置您的LoginModule类名称,您需要创建您的jaas模块配置文件并通过系统属性引用它,例如:-Djava.security.auth.login.config = path / to / your / login / config / file.cfg

示例配置:

 MyConfig { com.splwg.ejb.service.management.ABCDJMXLoginModule REQUIRED configKey1="config Value 1" configKey2="config Value 2" } 

在你的java代码中:

 env.put("jmx.remote.x.login.config", "MyConfig"); 

我也会删除

 env.put(ApplicationProperties.JMX_PWD_FILE_PROP, pwdFile); 

因为我认为它可能导致使用标准的jmx身份validation机制而不是JAAS(但我不确定)。

通过上述更改,您应该使用基于jaas的身份validation(使用自定义登录模块)和使用accFile进行授权的jmx。

只需按照这个有用的post来实现类似的东西。 我不得不在MyConfig语法中添加一些半冒号

 MyConfig { com.splwg.ejb.service.management.ABCDJMXLoginModule REQUIRED configKey1="config Value 1" configKey2="config Value 2"; }; 

还遵循原始ABCDJMXLoginModule类的代码:

 u_password = tmpPassword.toString(); 

应该:

 u_password = new String(tmpPassword);