如何加密 JConsole 密码文件的密码

发布于 2024-08-09 19:40:58 字数 574 浏览 4 评论 0原文

我正在使用 JConsole 访问我的应用程序 MBean,并使用 password.properties 文件。但根据 Sun 的规范,该文件仅包含明文格式的密码。

com.sun.management.jmxremote.password.file=/password.properties

现在我想加密密码并将其用于 JConsole 的 JMX 用户身份验证(用户名和密码远程部分中的字段)。我可以使用任何预定义的加密逻辑或我自己的加密算法。

有谁知道任何此类拦截将纯文本密码更改为加密密码,以便 JMX 框架也知道加密密码?

我当前的密码文件:

guest  guest
admin  admin

使用加密后,它应该如下所示:

guest  ENC(RjqpRYbAOwbAfAEDBdHJ7Q4l/GO5IoJidZctNT5oG64=)
admin  ENC(psg3EnDei6fVRuqHeLwOqNTgIWkwQTjI2+u2O7MXXWc=)

I am using the JConsole to access my application MBeans and i use the the password.properties file. But as per the Sun's specification this file contains passwords in clear text formats only.

com.sun.management.jmxremote.password.file=<someLocation>/password.properties

Now i would want to encrypt the password and use it for the JMX user authentication from JConsole (the username and password fields in Remote section). I could use any pre-defined encryption logic or my own encryption algorithms.

Does anyone know of any such interception to change the plain text password to encrypted one so that the JMX Framework too knows about the encrypted password?

My Current password file:

guest  guest
admin  admin

With Encryption it should look like:

guest  ENC(RjqpRYbAOwbAfAEDBdHJ7Q4l/GO5IoJidZctNT5oG64=)
admin  ENC(psg3EnDei6fVRuqHeLwOqNTgIWkwQTjI2+u2O7MXXWc=)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

朮生 2024-08-16 19:40:58

您可以使用management.properties文件中的配置参数com.sun.management.jmxremote.login.config(参见%JAVA_HOME%/lib/management/management.properties)来配置哪个Authenticator和LoginModule使用。

默认值如下:

JMXPluggableAuthenticator {
    com.sun.jmx.remote.security.FileLoginModule required;
};

读取纯文本密码文件jmxremote.password。由于com.sun.jmx.remote.security.JMXPluggableAuthenticator可以重新配置
要使用任何 LoginModule 实现,您可以自由选择现有的 LoginModule 或实现您自己的
它使用加密的密码文件。

要重新实现 FileLoginModule,您应该查看 attemptAuthentication(boolean) 方法,该方法
实际上执行身份验证并且您可能要替换它。实现 javax.security.auth.spi.LoginModule 接口
并使用给定的 CallbackHandler (您将从 init() 方法获取它)来请求用户名和密码。对收到的密码进行加密/散列,并将其与从加密密码文件中读取的密码进行比较。伪代码:

public class EncryptedFileLoginModule implements LoginModule {

@Override
public void initialize(Subject subject, CallbackHandler callbackHandler,
        Map<String, ?> sharedState, Map<String, ?> options) {
    this.subject = subject;
    this.callbackHandler = callbackHandler;
}

public boolean login() throws LoginException {
    attemptLogin();
    if (username == null || password == null) {
        throw new LoginException("Either no username or no password specified");
    }
    MessageDigest instance = MessageDigest.getInstance("SHA-1");
    byte[] raw = new String(password).getBytes();
    byte[] crypted = instance.digest(raw);
    // TODO: Compare to the one stored locally
    if (!authenticated) throw new LoginException();
    return true;
}

private void attemptLogin() throws LoginException {
    Callback[] callbacks = new Callback[2];
    callbacks[0] = new NameCallback("username");
    callbacks[1] = new PasswordCallback("password", false);
        callbackHandler.handle(callbacks);
        username = ((NameCallback) callbacks[0]).getName();
        user = new JMXPrincipal(username);
        char[] tmpPassword = ((PasswordCallback) callbacks[1]).getPassword();
        password = new char[tmpPassword.length];
        System.arraycopy(tmpPassword, 0, password, 0, tmpPassword.length);
        ((PasswordCallback) callbacks[1]).clearPassword();
}

但是,由于这已经是服务器端,如果您不强制执行,密码仍然会以纯文本形式传输
基于 SSL 的 JMX。因此,要么强制执行 SSL,要么使用另一种传输协议机制,在之前对凭据进行编码
通过电线传输它们。

总而言之,依赖 JAAS 提供的现有身份验证机制可能会更好。例如,如果
如果您在本地 Windows 环境中运行,则可以轻松使用 NTLoginModule 进行自动登录。但它只适用于本地机器。

创建文件 c:/temp/mysecurity.cfg:

MyLoginModule {
 com.sun.security.auth.module.NTLoginModule REQUIRED  debug=true debugNative=true;
};

接下来,配置 jmxremote.access 文件以包含您希望授予对 JMX 服务器的访问权限的用户名或角色:(

monitorRole readonly
controlRole readwrite ...
mhaller readonly

我建议启用调试模式,直到它正常工作。您将看到用户尝试登录时的所有用户名、域名和组名)
为您的服务器设置以下 JVM 参数:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8686
-Dcom.sun.management.jmxremote.authenticate=true
-Dcom.sun.management.jmxremote.ssl=true
-Djava.net.preferIPv4Stack=true
-Djava.security.auth.login.config=c:/temp/mysecurity.cfg
-Dcom.sun.management.jmxremote.login.config=MyLoginModule

启动您的应用程序并尝试使用 JConsole 或 VisualVM 进行连接。

请注意,在 JConsole 中,您将需要指定用户名和密码,尽管不会使用它。任何密码和任何用户名都可以。
原因是 jconsole 将尝试使用空用户名和空密码进行身份验证,而该操作被明确阻止。
当用户未输入任何内容时,VisualVM 通过使用空字符串作为用户名和密码来做得更好。

另请注意,远程连接时 NTLoginModule 不起作用,我认为您必须使用更复杂的登录模块,
但Sun已经提供了足够的:

  • com.sun.security.auth.module.Krb5LoginModule:使用Kerberos协议对用户进行身份验证
  • com.sun.security.auth.module.LdapLoginModule:(Java 6 中的新增功能):通过指定技术连接用户对 LDAP 服务器执行身份验证
  • com.sun.security.auth.module.JndiLoginModule: 对在 JNDI 上下文中注册的 LDAP 服务器执行身份验证
  • com.sun.security.auth.module.KeyStoreLoginModule:使用 Java 密钥库对用户进行身份验证。支持 PIN 或智能卡身份验证。

您将需要查看LdapLoginModule

You can use the configuration parameter com.sun.management.jmxremote.login.config in the management.properties file (see %JAVA_HOME%/lib/management/management.properties) to configure which Authenticator and LoginModule to use.

The default is the following:

JMXPluggableAuthenticator {
    com.sun.jmx.remote.security.FileLoginModule required;
};

which reads plain text password file jmxremote.password. Since the com.sun.jmx.remote.security.JMXPluggableAuthenticator can be reconfigured
to use any LoginModule implementation, you are free to either choose an existing LoginModule or to implement your own
which uses encrypted password files.

To reimplement FileLoginModule, you should have a look at the attemptAuthentication(boolean) method, which
actually performs the authentication and which you probably are going to replace. Implement the javax.security.auth.spi.LoginModule interface
and use the given CallbackHandler (you will get it from the init() method) to ask for a username and password. Encrypt/hash the received password and compare it against the one read from your encrypted password file. Pseudo code:

public class EncryptedFileLoginModule implements LoginModule {

@Override
public void initialize(Subject subject, CallbackHandler callbackHandler,
        Map<String, ?> sharedState, Map<String, ?> options) {
    this.subject = subject;
    this.callbackHandler = callbackHandler;
}

public boolean login() throws LoginException {
    attemptLogin();
    if (username == null || password == null) {
        throw new LoginException("Either no username or no password specified");
    }
    MessageDigest instance = MessageDigest.getInstance("SHA-1");
    byte[] raw = new String(password).getBytes();
    byte[] crypted = instance.digest(raw);
    // TODO: Compare to the one stored locally
    if (!authenticated) throw new LoginException();
    return true;
}

private void attemptLogin() throws LoginException {
    Callback[] callbacks = new Callback[2];
    callbacks[0] = new NameCallback("username");
    callbacks[1] = new PasswordCallback("password", false);
        callbackHandler.handle(callbacks);
        username = ((NameCallback) callbacks[0]).getName();
        user = new JMXPrincipal(username);
        char[] tmpPassword = ((PasswordCallback) callbacks[1]).getPassword();
        password = new char[tmpPassword.length];
        System.arraycopy(tmpPassword, 0, password, 0, tmpPassword.length);
        ((PasswordCallback) callbacks[1]).clearPassword();
}

However, as this is already the server-side, the password would afaik be still transferred in plain text if you don't enforce
JMX over SSL. So, either enforce SSL or use another transport protocol mechanism which encodes the credentials before
transmitting them over the wire.

To conclude, it's perhaps much better to rely on existing authentication mechanisms provided by JAAS. If, for example,
you're running in a local Windows environment, you can easily use the NTLoginModule for auto-login. But it only works on local machine.

Create a file c:/temp/mysecurity.cfg:

MyLoginModule {
 com.sun.security.auth.module.NTLoginModule REQUIRED  debug=true debugNative=true;
};

Next, configure the jmxremote.access file to contain the usernames or roles you wish to grant access to your JMX server:

monitorRole readonly
controlRole readwrite ...
mhaller readonly

(I recommend to enable debug mode until it works. You will see all the user names, domain names and group names when a user tries to log in)
Set the following JVM arguments for your server:

-Dcom.sun.management.jmxremote
-Dcom.sun.management.jmxremote.port=8686
-Dcom.sun.management.jmxremote.authenticate=true
-Dcom.sun.management.jmxremote.ssl=true
-Djava.net.preferIPv4Stack=true
-Djava.security.auth.login.config=c:/temp/mysecurity.cfg
-Dcom.sun.management.jmxremote.login.config=MyLoginModule

Start up your application and try to connect using JConsole or VisualVM.

Note that JConsole, you will need to specify a username and a password, although it's not going to be used. Any password and any username will work.
The reason is because jconsole will try to authenticate with null username and null password, which is blocked explicitly.
VisualVM does a better job by using empty strings for username and password when none are entered by the user.

Also note that the NTLoginModule does not work when connecting remotely, i think you would have to use a more sophisticated login module,
but Sun already provides enough of them:

  • com.sun.security.auth.module.Krb5LoginModule: Authenticates users using the Kerberos protocols
  • com.sun.security.auth.module.LdapLoginModule: (new in Java 6): Performs authentication against an LDAP server by specifying technical connection user
  • com.sun.security.auth.module.JndiLoginModule: Performs authentication against an LDAP server registered in the JNDI context
  • com.sun.security.auth.module.KeyStoreLoginModule: Authenticates users by using a Java Keystore. Supports PIN or smart card authentication.

You will want to have a look at the LdapLoginModule

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文