Custom Login Module for JMS in JBoss AS 5.1
arpit.todi Sep 16, 2011 2:45 AMHi,
I have deployed my application on JBoss AS 5.1. I want to restrict access to JMS Destinations and Connection Factories using my custom login module.
These are the steps I followed -
I created my login module and added its entry in login-config.xml file -
<application-policy name="MyLoginModule">
<authentication>
<login-module code="com.foo.MyLoginModule" flag="required">
</login-module>
</authentication>
</application-policy>
Then I specifiled my login module for security domain property for "SecurityStore" bean in "messaging\messaging-jboss-beans.xml" file -
<bean name="SecurityStore" class="org.jboss.jms.server.jbosssx.JBossASSecurityMetadataStore">
<!-- default security configuration -->
<property name="defaultSecurityConfig">
<![CDATA[
<security>
<role name="guest" read="true" write="true" create="true"/>
</security>
]]>
</property>
<property name="suckerPassword">CHANGE ME!!</property>
<property name="securityDomain">MyLoginModule</property>
<property name="securityManagement"><inject bean="JNDIBasedSecurityManagement"/></property>
<!-- @JMX annotation to export the management view of this bean -->
<annotation>@org.jboss.aop.microcontainer.aspects.jmx.JMX(name="jboss.messaging:service=SecurityStore",exposedInterface=org.jboss.jms.server.jbosssx.JBossASSecurityMetadataStoreMBean.class)</annotation>
<!-- Password Annotation to inject the password from the common password utility
<annotation>@org.jboss.security.integration.password.Password(securityDomain="MyLoginModule",methodName="setSuckerPassword")</annotation>
-->
</bean>
When I try to create queue connection from queue connection factory, queue connection creation request is intercepted by MyLoginModule, but I get null username and password from call backs.
Login Module code snippet -
Callback[] callbacks = new Callback[] {
new NameCallback("Username: "),
new PasswordCallback("Password: ", false)
};
try {
//_callbackHandler is initialized in login module from initialize method
_callbackHandler.handle(callbacks);
} catch (Exception e) {
_succeeded = false;
throw new LoginException(e.getMessage());
}
String userName = ((NameCallback)callbacks[0]).getName();
char[] passwd = ((PasswordCallback)callbacks[1]).getPassword();
String password = passwd != null ? new String(passwd) : null;
if (userName == null || userName.isEmpty())
{
throw new LoginException("Error: User information unavailable in CallbackHandler");
}
JMS Client code snippet -
Hashtable properties = new Hashtable();
properties.put(Context.INITIAL_CONTEXT_FACTORY, "org.jboss.security.jndi.JndiLoginInitialContextFactory");
properties.put(Context.PROVIDER_URL, "jnp://localhost:1099");
properties.put(Context.SECURITY_PRINCIPAL, "myuser");
properties.put(Context.SECURITY_CREDENTIALS, "mypassword");
InitialContext ctx = new InitialContext(properties);
QueueConnectionFactory qcf = (QueueConnectionFactory) ctx.lookup("MyQCF");
QueueConnection qc = qcf.createQueueConnection();
I get following exception -
javax.jms.JMSSecurityException: User null is NOT authenticated
at org.jboss.jms.server.jbosssx.JBossASSecurityMetadataStore.authenticate(JBossASSecurityMetadataStore.java:223)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.sun.jmx.mbeanserver.StandardMBeanIntrospector.invokeM2(StandardMBeanIntrospector.java:93)
at com.sun.jmx.mbeanserver.StandardMBeanIntrospector.invokeM2(StandardMBeanIntrospector.java:27)
at com.sun.jmx.mbeanserver.MBeanIntrospector.invokeM(MBeanIntrospector.java:208)
at com.sun.jmx.mbeanserver.PerInterface.invoke(PerInterface.java:120)
at com.sun.jmx.mbeanserver.MBeanSupport.invoke(MBeanSupport.java:262)
at javax.management.StandardMBean.invoke(StandardMBean.java:391)
at org.jboss.mx.server.RawDynamicInvoker.invoke(RawDynamicInvoker.java:164)
at org.jboss.mx.server.MBeanServerImpl.invoke(MBeanServerImpl.java:668)
at org.jboss.mx.util.MBeanProxyExt.invoke(MBeanProxyExt.java:210)
at $Proxy214.authenticate(Unknown Source)
at org.jboss.jms.server.endpoint.ServerConnectionFactoryEndpoint.createConnectionDelegateInternal(ServerConnectionFactoryEndpoint.java:233)
at org.jboss.jms.server.endpoint.ServerConnectionFactoryEndpoint.createConnectionDelegate(ServerConnectionFactoryEndpoint.java:171)
at org.jboss.jms.server.endpoint.advised.ConnectionFactoryAdvised.org$jboss$jms$server$endpoint$advised$ConnectionFactoryAdvised$createConnectionDelegate$aop(ConnectionFactoryAdvised.java:108)
at org.jboss.jms.server.endpoint.advised.ConnectionFactoryAdvised.createConnectionDelegate(ConnectionFactoryAdvised.java)
at org.jboss.jms.wireformat.ConnectionFactoryCreateConnectionDelegateRequest.serverInvoke(ConnectionFactoryCreateConnectionDelegateRequest.java:91)
at org.jboss.jms.server.remoting.JMSServerInvocationHandler.invoke(JMSServerInvocationHandler.java:143)
at org.jboss.remoting.ServerInvoker.invoke(ServerInvoker.java:891)
at org.jboss.remoting.transport.socket.ServerThread.completeInvocation(ServerThread.java:744)
at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:697)
at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:551)
at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:232)
at org.jboss.remoting.MicroRemoteClientInvoker.invoke(MicroRemoteClientInvoker.java:211)
at org.jboss.remoting.Client.invoke(Client.java:1724)
at org.jboss.remoting.Client.invoke(Client.java:629)
at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate.org$jboss$jms$client$delegate$ClientConnectionFactoryDelegate$createConnectionDelegate$aop(ClientConnectionFactoryDelegate.java:171)
at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate$createConnectionDelegate_N3019492359065420858.invokeTarget(ClientConnectionFactoryDelegate$createConnectionDelegate_N3019492359065420858.java)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:111)
at org.jboss.jms.client.container.StateCreationAspect.handleCreateConnectionDelegate(StateCreationAspect.java:81)
at org.jboss.aop.advice.org.jboss.jms.client.container.StateCreationAspect_z_handleCreateConnectionDelegate_18581223.invoke(StateCreationAspect_z_handleCreateConnectionDelegate_18581223.java)
at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:102)
at org.jboss.jms.client.delegate.ClientConnectionFactoryDelegate.createConnectionDelegate(ClientConnectionFactoryDelegate.java)
at org.jboss.jms.client.JBossConnectionFactory.createConnectionInternal(JBossConnectionFactory.java:205)
at org.jboss.jms.client.JBossConnectionFactory.createQueueConnection(JBossConnectionFactory.java:101)
at org.jboss.jms.client.JBossConnectionFactory.createQueueConnection(JBossConnectionFactory.java:95)
at com.foo.JMSSenderClient.sendMessage(GasOpsJMSSenderClient.java:60)
Am I doing something incorrect so that I am not getting username and password information through callbacks?
Please help!
Thanks,
Arpit