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