We’ve already seen how to set up simple security when we looked at the Duke’s Bank application (Section 4.3, “Security”). We looked at how to enable security by adding a security domain element to the jboss-specific deployment descriptors and thus linking your application to a configuration in the login-config.xml file. However we only used simple file based security in that chapter.
In this chapter, we’ll examine some more advanced configuration options and find out how to use some of the other login modules that are available.
One of the most likely scenarios is that your user and role information is stored and maintained in a database. JBoss comes with a login module called DatabaseServerLoginModule which just needs some simple configuration options to set it up. You need to supply the following.
the SQL query to retrieve the password for a specified user
the query to retrieve a user’s roles
the JNDI name of the DataSource to be used
This gives you the flexibility to use an existing database schema. Let’s suppose that the security database tables were created using the following SQ.L
CREATE TABLE Users(username VARCHAR(64) PRIMARY KEY, passwd VARCHAR(64)) CREATE TABLE UserRoles(username VARCHAR(64), userRoles VARCHAR(32))
then to use this as the security database for Duke’s Bank, you would modify the dukesbank entry in the JBoss login-config.xml file as follows:
<application-policy name="dukesbank"> <authentication> <login-module code="org.jboss.security.auth.spi.DatabaseServerLoginModule" flag="required"> <module-option name="dsJndiName">java:/DefaultDS</module-option> <module-option name="principalsQuery"> select passwd from Users where username=? </module-option> <module-option name="rolesQuery"> select userRoles,'Roles' from UserRoles where username=? </module-option> </login-module> </authentication> </application-policy>
The query to retrieve the password is straightforward. In the case of the roles query you will notice that there is an additional field with value Roles which is the role group. This allows you to store additional roles (for whatever purpose) classified by the role group. The ones which will affect JBoss permissions are expected to have the value Roles. In this simple example we only have a single set of roles in the database and no role group information[11].
We’ve used the default DataSource here. If you’re using Hypersonic, then you can easily create the tables and insert some data using the Database Manager tool which we also used in the Duke’s Bank chapter. Just execute the two commands above and then the following ones to insert the information for the user with customer id 200 and you should be able to login as before.
INSERT INTO Users VALUES(‘200’,’j2ee’) INSERT INTO UserRoles VALUES(‘200’,’BankCustomer’)
The login modules we’ve used so far all have support for password hashing; rather than storing passwords in plain text, a one-way hash of the password is stored (using an algorithm such as MD5) in a similar fashion to the /etc/passwd file on a UNIX system. This has the advantage that anyone reading the hash won’t be able to use it to log in. However, there is no way of recovering the password should the user forget it, and it also makes administration slightly more complicated because you also have to calculate the password hash yourself to put it in your security database. This isn’t a major problem though. To enable password hashing in the database example above, you would add the following module options to the configuration
<module-option name="hashAlgorithm">MD5</module-option> <module-option name="hashEncoding">base64</module-option>
This indicates that we want to use MD5 hashes and use base64 encoding to covert the binary hash value to a string. JBoss will now calculate the hash of the supplied password using these options before authenticating the user, so it’s important that we store the correctly hashed information in the database. If you’re on a UNIX system or have Cygwin installed on Windows, you can use openssl to hash the value.
$ echo -n "j2ee" | openssl dgst -md5 -binary | openssl base64 glcikLhvxq1BwPBZN0EGMQ==
You would then insert the resulting string, glcikLhvxq1BwPBZN0EGMQ==, into the database instead of the plaintext password, j2ee. If you don’t have this option, you can use the class org.jboss.security.Base64Encoder which you’ll find in the jbosssx.jar file.
$ java -classpath ./jbosssx.jar org.jboss.security.Base64Encoder j2ee MD5 [glcikLhvxq1BwPBZN0EGMQ==]
With a single argument it will just encode the given string but if you supply the name of a digest algorithm as a second argument it will calculate the hash of the string first.
[11] You can also use the default schema which is to have a table called Principals with columns PrincipalID and Password and a table called Roles with columns PrincipalID, Role and RoleGroup. In this case you don’t have to specify the SQL queries for the login module. The RoleGroup entries for JBoss permissions should be set to the value Roles as before.