For security concern, I decide to add in JMX authentication. It is very complicated to setup with Java's configuration. However, I managed to do so with Spring with two simple steps:
1. CustomJMXAuthenticator.java
package com.my.company.server;
import javax.management.remote.JMXAuthenticator;
import javax.management.remote.JMXPrincipal;
import javax.security.auth.Subject;
import org.apache.commons.lang.StringUtils;
/**
* @author Yaohua Wang
*
*/
public class CustomJMXAuthenticator implements JMXAuthenticator {
private String userName;
private String password;
public void setUserName(String userName) {
this.userName = userName;
}
public void setPassword(String password) {
this.password = password;
}
public Subject authenticate(Object credentials) {
if(credentials == null
|| !(credentials instanceof String[]))
throw new SecurityException("Credentials are required!");
String[] info = (String[]) credentials;
if(StringUtils.equals(info[0], userName)
&& StringUtils.equals(info[1], password)){
Subject subject = new Subject();
subject.getPrincipals().add(new JMXPrincipal(userName));
return subject;
}
throw new SecurityException("Unable to match credentials!");
}
}
2. Spring configuration:
<bean id="registry"
class="org.springframework.remoting.rmi.RmiRegistryFactoryBean"
destroy-method="destroy" autowire="no">
<property name="port" value="1099"/>
<property name="alwaysCreate" value="true"/>
</bean>
...
<bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean" autowire="no" depends-on="registry">
<property name="objectName" value="connector:name=rmi"/>
<property name="serviceUrl"
value="service:jmx:rmi:///jndi/rmi://localhost:1099/jmxrmi"/>
<property name="threaded" value="true"/>
<property name="daemon" value="true"/>
<property name="environmentMap">
<map>
<entry key="java.rmi.server.hostname" value="localhost"/>
<entry key="jmx.remote.authenticator">
<bean
class="com.my.company.server.CustomJMXAuthenticator">
<property name="userName" value="jmxuser"/>
<property name="password" value="jmxpassword"/>
</bean>
</entry>
</map>
</property>
</bean>
Now start the server and open jconsole. Type in following information:
- Remote Process: localhost:1099
- User Name: jmxuser
- Password: jmxpassword
1 comment:
Great article!
Do you know how to register such an authenticator class using annotations (without the XML configuration, but only properties file) in Spring Boot? Preferable 1.5.3.RELEASE
Thanks in advance
Post a Comment