Hi guys,
I put in a couple of simple classes that use the database for
authentication and principal-to-role mapping. These classes have a
high degree of cheese (no caching of database info, hard-coded
table and column names, hard-coded database pool name, no way
to actually use these classes without modifying source code, no
per-container configuration, etc.) but might be adequate for
someone who wanted to, for example, develop an application that
used information returned from getCallerPrincipal or isCallerInRole.
Also, it won't be that hard to de-cheese the code, but I've used my
jboss time quota for the week. Any volunteers? (Anyway, the next
thing I'm going to do is probably integrate security with Tomcat,
unless someone else does it first.)
For the adventurous who would like to try this (or even contribute),
here is a list of the necessary steps to get this to work (actually
setting a principal and a credential on the client was covered in an
earlier e-mail to this list AND is in bugzilla):
*** summary version ***
1. Add a minerva pool for security
2. Create the database tables
3. Hack the code to use the new classes
*** long version ***
1. Add a minerva pool with the JNDI name SecureDS. Here is my
entry from jboss.conf:
<MLET CODE="org.jboss.jdbc.XADataSourceLoader"
ARCHIVE="jboss.jar" CODEBASE="../lib/ext/">
<ARG TYPE="java.lang.String" VALUE="SecurityDS">
<ARG TYPE="java.lang.String"
VALUE="org.jboss.minerva.xa.XADataSourceImpl">
</MLET>
and here is my entry from jboss.jcml (sans user name and
password):
<mbean
name="DefaultDomain:service=XADataSource,name=SecurityDS">
<attribute
name="URL">jdbc:interbase://localhost/E:/book/bookdata.gdb</attr
ibute>
<attribute name="Password">****</attribute>
<attribute name="JDBCUser">****</attribute>
</mbean>
2. Add two tables to the corresponding data base:
CREATE TABLE SEC_ACCESS (NAME VARCHAR(50) NOT
NULL,
PASS VARCHAR(50) NOT NULL,
PRIMARY KEY (NAME));
CREATE TABLE SEC_ROLES (SETNAME VARCHAR(25) NOT
NULL,
PRINCIPAL VARCHAR(50) NOT NULL,
ROLENAME VARCHAR(50) NOT NULL,
PRIMARY KEY (SETNAME, PRINCIPAL, ROLENAME));
The sec_access table stores user-name / password values. The
sec_roles table maps principals to roles. Although eventually this
will be configurable per-bean (hence "setname" column--the name
of the set of mappings), right now it is hard-coded to use the value
"basic", so that is what you must have for every row (i.e. right there
is a universal principal to role mapping, contrary to the spec).
3. Currently in CVS, the container is hard-coded to use an
authentication that simply checks if the user name and password
are identical strings, and assumes that the principal name maps
one-to-one with an identical role name. Although the intent is to be
able to replace the authentication and role-mapping MBeans
dynamically per-container, right now what I did in testing is to
locally modify the classes org.jboss.security.SimpleRealmMapping
and org.jboss.security.EJBSecurityManagerService to instantiate
the new classes rather than those default ones. In
EJBSecurityManagerService, change initService to look like this:
protected void initService()
throws Exception
{
// Create a new SM
sm = new EJBSecurityManagerDatabaseImpl();
// Bind reference to SM in JNDI
Reference ref = new Reference(sm.getClass().toString(),
getClass().getName(), null);
new InitialContext().bind(JNDI_NAME, ref);
}
and in SimpleRealmMappingService modify initService to look like
this:
protected void initService()
throws Exception
{
// Create a new SM
srm = new DatabaseRealmMapping();
// Bind reference to JNDI
Reference ref = new
Reference(SimpleRealmMapping.class.toString(),
getClass().getName(), null);
new InitialContext().bind(JNDI_NAME, ref);
}
Also in SimpleRealmMappingService add the following import:
import org.jboss.system.RealmMapping;
and change the variable srm to be of type RealmMapping, i.e.:
public class SimpleRealmMappingService
extends ServiceMBeanSupport
implements SimpleRealmMappingServiceMBean, ObjectFactory
{
// Constants -----------------------------------------------------
public static String JNDI_NAME = "SimpleRealmMapping";
private static RealmMapping srm;
If anyone decides they want to play with this and runs into trouble,
please let me know.
-Dan