Howto: Calling EJB:s using EJB security and nukes userdefini
perre Jan 2, 2004 9:32 AMHi all!
Here is how to call EJB:s from Nukes, using EJB security with Nukes User- database. I have tested this using Jboss 3.2.2 and MySQL.
Step 1: Define a JBoss security domain using Nukes security definitions.
This is to tell JBoss EJB-layer how to access Nukes user database. Insert the following xml-fragment into the file %JBOSS_HOME%/server/default/conf/login-config.xml. There are already a number of security domains defined in that file, and this code should be inserted anywhere among the other definitions.
<application-policy name = "nukes"> <authentication> <login-module code = "org.jboss.security.auth.spi.DatabaseServerLoginModule" flag = "required"> <module-option name="unauthenticatedIdentity">guest</module-option> <module-option name="dsJndiName">java:/NukesDS</module-option> <module-option name="principalsQuery">select pn_pass from nuke_users where pn_uname=?</module-option> <module-option name="rolesQuery">select grp.pn_name, 'Roles' from nuke_groups grp, nuke_users usr, nuke_group_membership mem where usr.pn_uname=? and grp.pn_gid=mem.pn_gid and mem.pn_uid=usr.pn_uid</module-option> </login-module> </authentication> </application-policy>
Step 2: Declare security in the EJB.
You probably use Xdoclet or some other tool to make these definitions, but I give you here the resulting xml-files in the ejb-jar.
In the ejb-jar.xml:
Nothing JBoss- or Nukes specific here.
Declare the security roles in the assembly-descriptor-tag. These should be the same as your Nukes Groups.
<security-role> <role-name>Admins</role-name> </security-role> <security-role> <role-name>Users</role-name> </security-role>
Declare the method-permissions in the assembly-descriptor-tag. I suggest that you, in addition to you business methods, declare the method "ejbCreate" as unchecked.
<method-permission > <unchecked/> <method > <ejb-name>MyEjb</ejb-name> <method-intf>Home</method-intf> <method-name>create</method-name> <method-params /> </method> </method-permission>
In jboss.xml:
Set the security-domain and the unauthenticated-principal tags as in the following example. We defined both of those values in Step 1 above.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE jboss PUBLIC "-//JBoss//DTD JBOSS 2.4//EN" "http://www.jboss.org/j2ee/dtd/jboss_2_4.dtd"> <jboss> <security-domain>java:/jaas/nukes</security-domain> <unauthenticated-principal>guest</unauthenticated-principal> <enterprise-beans> <session> <ejb-name>MyEjb</ejb-name> <jndi-name>ejb/MyEjbHome</jndi-name> </session> </enterprise-beans> </jboss>
Deploy the ejb.
Step 3: Write the module or block.
Here is the complete code of a sample module that calls a secured ejb an displays the result.
/* * Created on 2004-jan-02 * */ package com.wizlog.demo.modules; import javax.ejb.CreateException; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.NameCallback; import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import org.jboss.nukes.html.Page; import org.jboss.nukes.module.ModuleSupport; import com.wizlog.demo.interfaces.MyEjb; import com.wizlog.demo.interfaces.MyEjbHome; /** * Sample module. * * @author Per-Erik Lindskog, Wizlog AB */ public class MyModule extends ModuleSupport { /** * @param name */ public MyModule(String name) { super(name); } public void main(Page page) { // Transfer the login information to the client-login LoginContext String username = null; String password = ""; LoginContext loginctx = null; if (this.getApi().userLoggedIn()) { username = this.getApi().currentUser().getUserName(); password = this.getApi().currentUser().getPassword(); CallbackHandler callbackHandler = null; callbackHandler = new UserPasswordHandler(username, password); try { String module = "client-login"; loginctx = new LoginContext(module, callbackHandler); loginctx.login(); } catch (LoginException e1) { e1.printStackTrace(); } } // Make the ejb call InitialContext context; MyEjbHome home; MyEJb myejb; try { context = new InitialContext(); home = (MyEjbHome) context.lookup("ejb/MyEjbHome"); myejb = home.create(); // Execute the call String result = myejb.myMethod(); // Display the result page.print("The result is: " + result); } catch (java.io.IOException e) { e.printStackTrace(); } catch (NamingException e) { e.printStackTrace(); } catch (CreateException e) { e.printStackTrace(); } // Clear the LoginContext if (loginctx != null) { try { loginctx.logout(); } catch (LoginException e1) { } } } /** * Simple JAAS callback handler that provides username and password. */ private class UserPasswordHandler implements CallbackHandler { private String username; private char[] password; /** * Constructs a callback handler. */ UserPasswordHandler(String username, String password) { this.username = username; this.password = password.toCharArray(); } /** * Handles the JAAS callbacks. */ public void handle(Callback[] callbacks) throws UnsupportedCallbackException { for (int i = 0; i < callbacks.length; i++) if (callbacks instanceof NameCallback) ((NameCallback) callbacks).setName(username); else if (callbacks instanceof PasswordCallback) ((PasswordCallback) callbacks).setPassword(password); else throw new UnsupportedCallbackException(callbacks); } } }
A part of this code is written and published by Peter Dornbush (http://www.luminis.nl/publications/websecurity.html)
A big thanks to him, and to all you people out there that makes all of this possible.
Good luck!
Brgds / Perre