This article describes my tests with ejb and JBoss7.
For my test a have ear (TestEar) with one ejb module (TestEjb) and one bean (TestBean).
TestEar.ear
+---TestEjb.ejb
+--mates.test.TestBean.class
mates.test.TestBeanRemote.class
As security I use RealmUsersRoles with
x-users.properties
testX=test1234
x-users.properties
testX=bean
And now standalone.xml
and I changed ApplicationRealm
<security-realm name="ApplicationRealm">
<authentication>
<jaas name="bean-sec-domain"/>
</authentication>
</security-realm>
and security domain
<security-domain name="bean-sec-domain" cache-type="default">
<authentication>
<login-module code="Remoting" flag="optional">
<module-option name="password-stacking" value="useFirstPass"/>
</login-module>
<login-module code="org.jboss.security.auth.spi.UsersRolesLoginModule" flag="required">
<module-option name="defaultUsersProperties" value="file:/${jboss.server.config.dir}/x-users.properties"/>
<module-option name="defaultRolesProperties" value="file:/${jboss.server.config.dir}/x-roles.properties"/>
<module-option name="usersProperties" value="file:/${jboss.server.config.dir}/x-users.properties"/>
<module-option name="rolesProperties" value="file:/${jboss.server.config.dir}/x-roles.properties"/>
<module-option name="password-stacking" value="useFirstPass"/>
</login-module>
</authentication>
</security-domain>
And now lets look at bean.
@Stateless
@DeclareRoles("bean")
public class TestBean implements TestBeanRemote {
@Resource
private EJBContext context;
@Override
@RolesAllowed("bean")
public String getName ()
{
getNameFree();
}
@Override
public String getNameFree ()
{
String aName = "";
if (context.getCallerPrincipal() != null) {
aName = context.getCallerPrincipal().getName();
}
return "name " + aName + " " + context.isCallerInRole("bean");
}
}
Let's secure EJB
add jboss-app.xml to TestEar.ear\META-INF. I use security domain other to ensure that i secure all beans.
<?xml version="1.0" encoding="UTF-8"?>
<p:jboss-app xmlns:p="http://www.jboss.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.jboss.com/xml/ns/javaee ../../xsd/jboss-app_7_0.xsd ">
<security-domain>other</security-domain>
</p:jboss-app>
And I want to secure TestBean. I have to add jboss-ejb3.xml to TestEjb.jar\META-INF\. TestBean is secured by bean-sec-domain.
<?xml version="1.0" encoding="UTF-8"?>
<jboss:ejb-jar xmlns:jboss="http://www.jboss.com/xml/ns/javaee"
xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="urn:security" version="3.1" impl-version="2.0">
<assembly-descriptor xmlns="http://java.sun.com/xml/ns/javaee">
<security:security xmlns:security="urn:security">
<security:security-domain>bean-sec-domain</security:security-domain>
<ejb-name>TestBean</ejb-name>
</security:security>
</assembly-descriptor>
</jboss:ejb-jar>
Remote interface is realz simple with 2 methods.
Client:
Hashtable<String, Object> p = new Hashtable<String, Object>();
p.put(Context.INITIAL_CONTEXT_FACTORY, InitialContextFactory.class.getName());
p.put(Context.PROVIDER_URL, "remote://127.0.0.1:4447/");
p.put(InitialContext.SECURITY_PRINCIPAL, "testX");
p.put(InitialContext.SECURITY_CREDENTIALS, "test1234");
p.put("jboss.naming.client.ejb.context", true);
p.put("jboss.naming.client.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT", "false");
InitialContext c = new InitialContext(p);
TestBeanRemote vLookup = (TestBeanRemote) c.lookup("java:/TestEar/TestEjb/TestBean!"+ TestBeanRemote.class.getName());
System.out.println("x" + vLookup.getNameFree());
System.out.println("x" + vLookup.getName());
After this you can see
xname testX true
xsecured name testX true
That's all.
And now some other tests:
Most important mart is
p.put("jboss.naming.client.ejb.context", true);
witout this property you wil see "No EJB receiver available for handling [appName:TestEar,modulename:TestEjb,distinctname:] combination"
when you put in class path file jboss-ejb-client.properties with standard
remote.connectionprovider.create.options.org.xnio.Options.SSL_ENABLED=false
remote.connections=x1
remote.connection.x1.host=127.0.0.1
remote.connection.x1.port = 4447
remote.connection.x1.connect.options.org.xnio.Options.SASL_POLICY_NOANONYMOUS=false
remote.connection.x1.connect.options.org.xnio.Options.SASL_POLICY_NOPLAINTEXT=false
and comment p.put("jboss.naming.client.ejb.context", true);
and in console is now
xname $local false
Exception in thread "main" javax.ejb.EJBAccessException: JBAS014502: Invocation on method: public abstract java.lang.String mates.test.TestBeanRemote.getName() of bean: TestBean is not allowed
jboss.naming.client.ejb.context setup EJBContext on client side. See org.jboss.naming.remote.client.InitialContextFactory