Enterprise Java Development@TOPIC@
JBoss Remoting and JNDI InitialContext
EJBClient and JNDI InitialContext
Changing Users
Access Violations
Access Granted
Used to perform JMS and other non-EJB resource lookups
java.naming.factory.initial=org.wildfly.naming.client.WildFlyInitialContextFactory java.naming.factory.url.pkgs= java.naming.provider.url=http-remoting://127.0.0.1:8080
factory.initial set to WildFlyInitialContextFactory implementation
compatible with both JBoss Remoting and EJBClient
provider.url set to address of JBoss server
url.pkgs option not needed with Wildfly implementation (e.g., "ejb:")
securePingEAR/securePingEJB/SecurePingEJB!info.ejava.examples.secureping.ejb.SecurePingRemote
Using generic JBoss Remoting JNDI name
private Context runAs(String[] login) throws NamingException, IOException {
Properties env = new Properties(); //load the defaults from jndi.properties
if (login != null) {
env.put(Context.SECURITY_PRINCIPAL, login[0]);
env.put(Context.SECURITY_CREDENTIALS, login[1]);
}
return new InitialContext(env);
}
Client provides credentials in JNDI prior to obtaining InitialContext
Must use current JNDI Context to lookup @Remote
Must leave JNDI Context open while making calls on @Remote interface
protected String[] userLogin = new String[] { userUser, userPassword };
protected String[] adminLogin = new String[] { adminUser, adminPassword };
jndi=runAs(userLogin);
ejb=(SecurePing)jndi.lookup(jndiName);
assertFalse("user in admin role", ejb.isCallerInRole("admin"));
assertTrue("user not in user role", ejb.isCallerInRole("user"));
jndi.close();
jndi=runAs(adminLogin);
ejb=(SecurePing)jndi.lookup(jndiName);
assertTrue("admin not in admin role", ejb.isCallerInRole("admin"));
assertTrue("admin not in user role", ejb.isCallerInRole("user"));
jndi.close();
Client can switch credentials with a change in InitialContexts and @Remote reference
Primary means to communicate with EJB using RMI
Leverages vendor knowledge of EJB and specific @Remote interface
java.naming.factory.initial=org.wildfly.naming.client.WildFlyInitialContextFactory java.naming.factory.url.pkgs= java.naming.provider.url=http-remoting://127.0.0.1:8080
factory.initial not important if url.pkgs extension supplied
WildFlyInitialContextFactory performs this automatically
provider.url same as with JBoss Remoting
ejb:securePingEAR/securePingEJB/SecurePingEJB!info.ejava.examples.secureping.ejb.SecurePingRemote
Using EJBClient JNDI name prefix ("ejb:")
protected static String[] currentLogin;
private void runAs(String[] login) throws NamingException, IOException {
if (!Arrays.equals(login, currentLogin) || securePing==null) {
Properties props = new Properties(); //initialize with values from jndi.properties
if (login!=null) {
props.put(Context.SECURITY_PRINCIPAL, login[0]);
props.put(Context.SECURITY_CREDENTIALS, login[1]);
}
InitialContext jndi = null;
try {
jndi = new InitialContext(props);
securePing = (SecurePingRemote)jndi.lookup(jndiName);
currentLogin = login;
} finally {
if (jndi!=null) { jndi.close(); }
}
}
}
EJBClient stores credentials with connection
No security need to keep InitialContext open
protected String[] userLogin = new String[] { userUser, userPassword };
protected String[] adminLogin = new String[] { adminUser, adminPassword };
runAs(userLogin);
assertFalse("user in admin role", securePing.isCallerInRole("admin"));
assertTrue("user not in user role", securePing.isCallerInRole("user"));
runAs(adminLogin);
assertTrue("admin not in admin role", securePing.isCallerInRole("admin"));
assertTrue("admin not in user role", securePing.isCallerInRole("user"));
No need to get new InitialContext or new lookup of @Remote
Useful to implement sanity check to assure authentication and authorizations in place
@Stateless
public class SecurePingEJB implements SecurePingRemote, SecurePingLocal {
@Resource
SessionContext ctx;
@PermitAll
public String whoAmI() {
String name= ctx.getCallerPrincipal().getName();
logger.debug("whoAmI()={}", name);
return name;
}
Implement debug method to return authenticated identity
@PermitAll
public boolean isCallerInRole(String role) {
boolean result = ctx.isCallerInRole(role);
logger.debug("user={}, isCallerInRole({})={}", ctx.getCallerPrincipal().getName(), role, result);
return result;
}
Implement debug method to return role query result
runAs(userLogin);
assertEquals("unexpected user", userUser, securePing.whoAmI());
assertFalse("user in internalRole role", securePing.isCallerInRole("internalRole"));
runAs(adminLogin);
assertEquals("unexpected user", adminUser, securePing.whoAmI());
assertTrue("admin not in internalRole role", securePing.isCallerInRole("internalRole"));
Client asserts security query results to verify setup correctly
Context jndi = new InitialContext();
logger.debug("looking up jndi.name={}", jndiName);
securePing = (SecurePingRemote)jndi.lookup(jndiName);
try {
runAs(userLogin);
logger.info(securePing.pingAdmin());
fail("didn't detect non-admin user");
}
catch (EJBAccessException ex) {
logger.info("expected exception thrown:" + ex);
}
-looking up jndi.name=ejb:securePingEAR/securePingEJB/SecurePingEJB !info.ejava.examples.secureping.ejb.SecurePingRemote as user1 -found=Proxy for remote EJB StatelessEJBLocator for "securePingEAR/securePingEJB/SecurePingEJB", view is interface info.ejava.examples.secureping.ejb.SecurePingRemote, affinity is None -login=[user1, password1!], whoAmI=user1 -expected exception thrown:javax.ejb.EJBAccessException: WFLYEJB0364: Invocation on method: public abstract java.lang.String info.ejava.examples.secureping.ejb.SecurePing.pingAdmin() of bean: SecurePingEJB is not allowed
EJBAccessException thrown when accessing method not allowed
runAs(adminLogin);
logger.info(securePing.pingAdmin());
-looking up jndi.name=ejb:securePingEAR/securePingEJB/SecurePingEJB !info.ejava.examples.secureping.ejb.SecurePingRemote as admin1 -found=Proxy for remote EJB StatelessEJBLocator for "securePingEAR/securePingEJB/SecurePingEJB", view is interface info.ejava.examples.secureping.ejb.SecurePingRemote, affinity is None -login=[admin1, password1!], whoAmI=admin1 -called pingAdmin, principal=admin1, isUser=true, isAdmin=true, isInternalRole=true
Access to method protected by declarative security granted
Results of programmatic security checks returned in formatted text string