使用自定义 JAAS 登录模块启动 JMX 代理,将 login() 设置为始终 return true
Launching a JMX agent with a custom JAAS login module, setting login() to always return true
我正在为 JMX 实例构建自定义 JAAS 模块。正在 运行 的文件如下:
MBean 接口
package com.this.mbean;
public interface ImplementationMBean {
public void setName(String name);
public String getName();
public void setNumber(int number);
public int getNumber();
public boolean getKilled();
public void setKilled(boolean killed);
}
实施Class
package com.test.mbean;
public class Implementation implements ImplementationMBean {
private String name ;
private int number;
private boolean killed = false;
public Implementation(String name, int number) {
this.name = name;
this.number = number;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public void setNumber(int number) {
this.number = number;
}
@Override
public int getNumber() {
return number;
}
@Override
public boolean getKilled() {
return killed;
}
@Override
public void setKilled(boolean killed) {
this.killed = killed;
}
}
RunningImplementationClass
package com.test.running;
import java.lang.management.ManagementFactory;
import com.test.mbean.*;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
public class RunningImplementation {
public static final String name = "defaultName";
public static final int number = 100;
public static void main(String[] args)
throws MalformedObjectNameException, InterruptedException,
InstanceAlreadyExistsException, MBeanRegistrationException,
NotCompliantMBeanException{
//get MBean Server
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
//register MBean
ImplementationMBean mBean = new Implementation(name, number);
ObjectName name = new ObjectName("com.bard.mbean:type=ConcreteImplementation");
mbs.registerMBean(mBean, name);
do{
Thread.sleep(1000);
System.out.println("Name = " + mBean.getName() + ", number = " + mBean.getNumber());
}while(mBean.getKilled() == false);
}
}
这被打包到一个名为 MBeanSecure.jar 的 JAR 文件中。
我启用了 jmx 代理:
-Dcom.sun.management.jmxremote
我已将其设置为 运行 在本地主机上的端口 1234:
-Dcom.sun.management.jmxremote.port=1234
我已将 JMX 代理配置为使用指定的 JAAS 配置条目:
-Dcom.sun.management.login.config=Sample
并指定 Jaas 配置文件的路径:
-Djava.security.auth.login.config=sample_jaas.config
sample_jaas.config
Sample {
sample.module.SampleLoginModule required debug=true;
authIdentity=monitorRole;
};
监控角色在jmxremote.access
中指定
-Dcom.sun.management.jmxremote.access.file=jmxremote.access
看起来像这样:
monitorRole readonly
controleRole readwrite
我的登录模块很简单,因为 returns 无论如何都是真的。
示例登录模块
package sample.module;
import java.util.*;
import java.io.IOException;
import javax.security.auth.*;
import javax.security.auth.callback.*;
import javax.security.auth.login.*;
import javax.security.auth.spi.*;
import sample.principal.SamplePrincipal;
public class SampleLoginModule implements LoginModule {
// initial state
private Subject subject;
private CallbackHandler callbackHandler;
private Map sharedState;
private Map options;
// configurable option
private boolean debug = false;
// the authentication status
private boolean succeeded = false;
private boolean commitSucceeded = false;
// username and password
private String username;
private char[] password;
// testUser's SamplePrincipal
private SamplePrincipal userPrincipal;
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options) {
this.subject = subject;
this.callbackHandler = callbackHandler;
this.sharedState = sharedState;
this.options = options;
// initialize any configured options
debug = "true".equalsIgnoreCase((String)options.get("debug"));
}
public boolean login() throws LoginException {
return true;
}
public boolean commit() throws LoginException {
if (succeeded == false) {
return false;
} else {
// add a Principal (authenticated identity)
// to the Subject
// assume the user we authenticated is the SamplePrincipal
userPrincipal = new SamplePrincipal(username);
if (!subject.getPrincipals().contains(userPrincipal))
subject.getPrincipals().add(userPrincipal);
if (debug) {
System.out.println("\t\t[SampleLoginModule] " +
"added SamplePrincipal to Subject");
}
// in any case, clean out state
username = null;
for (int i = 0; i < password.length; i++)
password[i] = ' ';
password = null;
commitSucceeded = true;
return true;
}
}
public boolean abort() throws LoginException {
if (succeeded == false) {
return false;
} else if (succeeded == true && commitSucceeded == false) {
// login succeeded but overall authentication failed
succeeded = false;
username = null;
if (password != null) {
for (int i = 0; i < password.length; i++)
password[i] = ' ';
password = null;
}
userPrincipal = null;
} else {
// overall authentication succeeded and commit succeeded,
// but someone else's commit failed
logout();
}
return true;
}
public boolean logout() throws LoginException {
subject.getPrincipals().remove(userPrincipal);
succeeded = false;
succeeded = commitSucceeded;
username = null;
if (password != null) {
for (int i = 0; i < password.length; i++)
password[i] = ' ';
password = null;
}
userPrincipal = null;
return true;
}
}
与校长 class:
示例主体
package sample.principal;
import java.security.Principal;
public class SamplePrincipal implements Principal, java.io.Serializable {
private String name;
public SamplePrincipal(String name) {
if (name == null)
throw new NullPointerException("illegal null input");
this.name = name;
}
public String getName() {
return name;
}
public String toString() {
return("SamplePrincipal: " + name);
}
public boolean equals(Object o) {
if (o == null)
return false;
if (this == o)
return true;
if (!(o instanceof SamplePrincipal))
return false;
SamplePrincipal that = (SamplePrincipal)o;
if (this.getName().equals(that.getName()))
return true;
return false;
}
public int hashCode() {
return name.hashCode();
}
}
当我运行代码使用:
java -Dcom.sun.management.jmxremote.port=1234 -Dcom.sun.management.jmxremote.login.config=Sample -Dcom.java.security.auth.login.config=sample_jaas.config -Djava.security.policy==sampleazn.policy -Dcom.sun.management.jmxremote.access.file=jmxremote.access -jar MBeanSecure.jar
代码运行s,定时输出
Name = defaultName, number = 100
然后我尝试通过 JConsole 访问 JMX 代理
jconsole
这将打开 Jconsole window 显示进程 运行ning。
但是,当我尝试将其作为远程进程连接时,出现“连接失败”错误。这很难调试,因为我看不到任何失败的日志。我认为通过使用
是对的吗
com.sun.management.jmxremote.login.config
我覆盖了默认的登录行为?在这种情况下,它应该检查我的 Jaas 配置,运行 登录模块,它总是 returns true,并允许用户在指定的 monitorRole 下?
我认为错误出在配置文件上,但由于文档稀少,很难确认设置或调试。
已解决:
我可以通过 运行 调试问题:
jconsole -debug
这表明我的配置文件有语法错误,需要:
Sample {
sample.module.SampleLoginModule required debug=true
authIdentity=monitorRole;
};
代替
Sample {
sample.module.SampleLoginModule required debug=true;
authIdentity=monitorRole;
};
注意单个分号
我想修复此代码中的错误。
仅更改登录方法:
System.out.println("Login Module - login called");
if (callbackHandler == null) {
throw new LoginException("Oops, callbackHandler is null");
}
Callback[] callbacks = new Callback[2];
callbacks[0] = new NameCallback("name:");
callbacks[1] = new PasswordCallback("password:", false);
try {
callbackHandler.handle(callbacks);
} catch (IOException e) {
throw new LoginException("Oops, IOException calling handle on callbackHandler");
} catch (UnsupportedCallbackException e) {
throw new LoginException("Oops, UnsupportedCallbackException calling handle on callbackHandler");
}
NameCallback nameCallback = (NameCallback) callbacks[0];
PasswordCallback passwordCallback = (PasswordCallback) callbacks[1];
String name = nameCallback.getName();
String password = new String(passwordCallback.getPassword());
if ("sohanb".equals(name) && "welcome".equals(password)) {
System.out.println("Success! You get to log in!");
user = new JMXPrincipal(name);
succeeded = true;
return succeeded;
} else {
System.out.println("Failure! You don't get to log in");
succeeded = false;
throw new FailedLoginException("Sorry! No login for you.");
}
已添加:user = new JMXPrincipal(name);
同时注释 commit() 函数中的所有代码行,然后添加:
subject.getPrincipals().add(user);
我正在为 JMX 实例构建自定义 JAAS 模块。正在 运行 的文件如下:
MBean 接口
package com.this.mbean;
public interface ImplementationMBean {
public void setName(String name);
public String getName();
public void setNumber(int number);
public int getNumber();
public boolean getKilled();
public void setKilled(boolean killed);
}
实施Class
package com.test.mbean;
public class Implementation implements ImplementationMBean {
private String name ;
private int number;
private boolean killed = false;
public Implementation(String name, int number) {
this.name = name;
this.number = number;
}
@Override
public void setName(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
@Override
public void setNumber(int number) {
this.number = number;
}
@Override
public int getNumber() {
return number;
}
@Override
public boolean getKilled() {
return killed;
}
@Override
public void setKilled(boolean killed) {
this.killed = killed;
}
}
RunningImplementationClass
package com.test.running;
import java.lang.management.ManagementFactory;
import com.test.mbean.*;
import javax.management.InstanceAlreadyExistsException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
public class RunningImplementation {
public static final String name = "defaultName";
public static final int number = 100;
public static void main(String[] args)
throws MalformedObjectNameException, InterruptedException,
InstanceAlreadyExistsException, MBeanRegistrationException,
NotCompliantMBeanException{
//get MBean Server
MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
//register MBean
ImplementationMBean mBean = new Implementation(name, number);
ObjectName name = new ObjectName("com.bard.mbean:type=ConcreteImplementation");
mbs.registerMBean(mBean, name);
do{
Thread.sleep(1000);
System.out.println("Name = " + mBean.getName() + ", number = " + mBean.getNumber());
}while(mBean.getKilled() == false);
}
}
这被打包到一个名为 MBeanSecure.jar 的 JAR 文件中。
我启用了 jmx 代理:
-Dcom.sun.management.jmxremote
我已将其设置为 运行 在本地主机上的端口 1234:
-Dcom.sun.management.jmxremote.port=1234
我已将 JMX 代理配置为使用指定的 JAAS 配置条目:
-Dcom.sun.management.login.config=Sample
并指定 Jaas 配置文件的路径:
-Djava.security.auth.login.config=sample_jaas.config
sample_jaas.config
Sample {
sample.module.SampleLoginModule required debug=true;
authIdentity=monitorRole;
};
监控角色在jmxremote.access
中指定-Dcom.sun.management.jmxremote.access.file=jmxremote.access
看起来像这样:
monitorRole readonly
controleRole readwrite
我的登录模块很简单,因为 returns 无论如何都是真的。
示例登录模块
package sample.module;
import java.util.*;
import java.io.IOException;
import javax.security.auth.*;
import javax.security.auth.callback.*;
import javax.security.auth.login.*;
import javax.security.auth.spi.*;
import sample.principal.SamplePrincipal;
public class SampleLoginModule implements LoginModule {
// initial state
private Subject subject;
private CallbackHandler callbackHandler;
private Map sharedState;
private Map options;
// configurable option
private boolean debug = false;
// the authentication status
private boolean succeeded = false;
private boolean commitSucceeded = false;
// username and password
private String username;
private char[] password;
// testUser's SamplePrincipal
private SamplePrincipal userPrincipal;
public void initialize(Subject subject, CallbackHandler callbackHandler,
Map sharedState, Map options) {
this.subject = subject;
this.callbackHandler = callbackHandler;
this.sharedState = sharedState;
this.options = options;
// initialize any configured options
debug = "true".equalsIgnoreCase((String)options.get("debug"));
}
public boolean login() throws LoginException {
return true;
}
public boolean commit() throws LoginException {
if (succeeded == false) {
return false;
} else {
// add a Principal (authenticated identity)
// to the Subject
// assume the user we authenticated is the SamplePrincipal
userPrincipal = new SamplePrincipal(username);
if (!subject.getPrincipals().contains(userPrincipal))
subject.getPrincipals().add(userPrincipal);
if (debug) {
System.out.println("\t\t[SampleLoginModule] " +
"added SamplePrincipal to Subject");
}
// in any case, clean out state
username = null;
for (int i = 0; i < password.length; i++)
password[i] = ' ';
password = null;
commitSucceeded = true;
return true;
}
}
public boolean abort() throws LoginException {
if (succeeded == false) {
return false;
} else if (succeeded == true && commitSucceeded == false) {
// login succeeded but overall authentication failed
succeeded = false;
username = null;
if (password != null) {
for (int i = 0; i < password.length; i++)
password[i] = ' ';
password = null;
}
userPrincipal = null;
} else {
// overall authentication succeeded and commit succeeded,
// but someone else's commit failed
logout();
}
return true;
}
public boolean logout() throws LoginException {
subject.getPrincipals().remove(userPrincipal);
succeeded = false;
succeeded = commitSucceeded;
username = null;
if (password != null) {
for (int i = 0; i < password.length; i++)
password[i] = ' ';
password = null;
}
userPrincipal = null;
return true;
}
}
与校长 class:
示例主体
package sample.principal;
import java.security.Principal;
public class SamplePrincipal implements Principal, java.io.Serializable {
private String name;
public SamplePrincipal(String name) {
if (name == null)
throw new NullPointerException("illegal null input");
this.name = name;
}
public String getName() {
return name;
}
public String toString() {
return("SamplePrincipal: " + name);
}
public boolean equals(Object o) {
if (o == null)
return false;
if (this == o)
return true;
if (!(o instanceof SamplePrincipal))
return false;
SamplePrincipal that = (SamplePrincipal)o;
if (this.getName().equals(that.getName()))
return true;
return false;
}
public int hashCode() {
return name.hashCode();
}
}
当我运行代码使用:
java -Dcom.sun.management.jmxremote.port=1234 -Dcom.sun.management.jmxremote.login.config=Sample -Dcom.java.security.auth.login.config=sample_jaas.config -Djava.security.policy==sampleazn.policy -Dcom.sun.management.jmxremote.access.file=jmxremote.access -jar MBeanSecure.jar
代码运行s,定时输出
Name = defaultName, number = 100
然后我尝试通过 JConsole 访问 JMX 代理
jconsole
这将打开 Jconsole window 显示进程 运行ning。
但是,当我尝试将其作为远程进程连接时,出现“连接失败”错误。这很难调试,因为我看不到任何失败的日志。我认为通过使用
是对的吗com.sun.management.jmxremote.login.config
我覆盖了默认的登录行为?在这种情况下,它应该检查我的 Jaas 配置,运行 登录模块,它总是 returns true,并允许用户在指定的 monitorRole 下?
我认为错误出在配置文件上,但由于文档稀少,很难确认设置或调试。
已解决:
我可以通过 运行 调试问题:
jconsole -debug
这表明我的配置文件有语法错误,需要:
Sample {
sample.module.SampleLoginModule required debug=true
authIdentity=monitorRole;
};
代替
Sample {
sample.module.SampleLoginModule required debug=true;
authIdentity=monitorRole;
};
注意单个分号
我想修复此代码中的错误。 仅更改登录方法:
System.out.println("Login Module - login called");
if (callbackHandler == null) {
throw new LoginException("Oops, callbackHandler is null");
}
Callback[] callbacks = new Callback[2];
callbacks[0] = new NameCallback("name:");
callbacks[1] = new PasswordCallback("password:", false);
try {
callbackHandler.handle(callbacks);
} catch (IOException e) {
throw new LoginException("Oops, IOException calling handle on callbackHandler");
} catch (UnsupportedCallbackException e) {
throw new LoginException("Oops, UnsupportedCallbackException calling handle on callbackHandler");
}
NameCallback nameCallback = (NameCallback) callbacks[0];
PasswordCallback passwordCallback = (PasswordCallback) callbacks[1];
String name = nameCallback.getName();
String password = new String(passwordCallback.getPassword());
if ("sohanb".equals(name) && "welcome".equals(password)) {
System.out.println("Success! You get to log in!");
user = new JMXPrincipal(name);
succeeded = true;
return succeeded;
} else {
System.out.println("Failure! You don't get to log in");
succeeded = false;
throw new FailedLoginException("Sorry! No login for you.");
}
已添加:user = new JMXPrincipal(name);
同时注释 commit() 函数中的所有代码行,然后添加:
subject.getPrincipals().add(user);