Remote EJB invocation to clustered wildfly with JAAS
faxe13 Aug 22, 2013 3:34 AMHi,
We are facing serious troubles when trying to invoke secured EJB methods from remote EJB clients (in a standalone VM, no application server). What we are seeing is that the invocation on the first cluster node will contain the users principal and credentials witout any problem but the second node (invoked because of load balancing) will ony have the default-user $local as configred in the standalone-full-ha.xml for the ApplicationRealm.
We are using Java 7 and the Alpha 4 version of wildfly using http-remoting. The cluster environment uses the standalone-full-ha.xml configuration with a custom security domain using the
RemotingLoginModule. We have tried using remote naming as well as the EJB-Client API with the same effects.
<security-domain name="testdomain" cache-type="default">
<authentication>
<login-module code="org.jboss.as.security.remoting.RemotingLoginModule" flag="required">
<module-option name="useFirstPass" value="true"/>
</login-module>
</authentication>
</security-domain>
Our Client code is very simple and looks as follows:
Hashtable<String, Object> env = new Hashtable<String, Object>();
env.put("java.naming.factory.initial", "org.jboss.naming.remote.client.InitialContextFactory");
env.put("java.naming.provider.url", "http-remoting://localhost:8080,http-remoting://localhost:8180");
env.put("jboss.naming.client.ejb.context", "true");
env.put(Context.SECURITY_PRINCIPAL, "aut");
env.put(Context.SECURITY_CREDENTIALS, "aut1234#");
InitialContext jndiCtx = new InitialContext(env);
for (int i = 0; i<10; i++) {
SecuredBeanRemote bean = (SecuredBeanRemote) jndiCtx.lookup(
"securedbean/SecuredBean!com.test.securedbean.SecuredBeanRemote");
bean.test("text " + i);
}
The bean which gets deployed in a jar file is also very simple:
@Stateless
@Clustered
@SecurityDomain("testdomain")
public class SecuredBean implements SecuredBeanRemote {
@Resource
private SessionContext ctx;
@PermitAll
public String test(String text) {
System.out.println("received: " + text + " from " + ctx.getCallerPrincipal().getName());
return "xx" + text;
}
}
@Remote
public interface SecuredBeanRemote {
public String test(String text);
}
The println on the first node will print "aut" as caller principal and the second node will print $local. We are able to reproduce that always the node that gets the first call will print the principal correctly. If we switch the nodes in the provider.url than the second node will get the first invocation and print the caller principal correctly and the first node will print $local.
Is there anything we can do to get the caller principal propageted correctly on every node ?
Another question that comes to our mind is if we should keep one InitialContext instance around for all server invocations of one client or create a new instance for each method call. In our tests we were getting "java.lang.IllegalStateException: EJBCLIENT000025: No EJB receiver available for handling" exceptions after about 90 invocations from one client when creating new instances so we decided to keep on instance. But if we are keeping the InitialContext instance we might have troubles providing different credentials for subsequent method calls and would need to synchronize on each call.
Cheers, Gert