One great thing about Geronimo, besides being fully J2EE compatible, open source, and packaged with the Apache license, is its extreme modularity. The kernel is compact, allowing modules like Apache Derby to be added and removed from the kernel through Geronimo Beans (GBeans). In fact, Derby is built into Geronimo by default, which makes Derby and Geronimo a good combination for Geronimo applications. In my previous article, "Restrict directory access in Apache Geronimo," (developerWorks, November 2005), two properties files held the user and password information. This approach required manually entering user IDs and passwords to these properties files. This two-part article series takes a different approach to authentication, which is accomplished by querying Geronimo's built-in Derby database. This allows you to not only store the username and password information, but also other personal and identifying information about a user, such as an e-mail address. This form of database authentication becomes more important as the size of a business increases, which will clearly benefit the clients of our fictional Web Apps Corp.
In this article, you take advantage of Derby to store more information than just a username and password. You create a simple login system where users can visit and log in using form-based authentication and J2EE declarative security using Geronimo's SQLLoginModule. Usernames, passwords, and other information are stored in Geronimo's built-in Derby database and in a table containing username-to-group mappings.
This article teaches you how to create and initialize these tables in Geronimo's built-in Derby database. The new tables contain initial login data for testing the application, and the SQLLoginModule connects to the database to obtain username and password information. Security is implemented through a database deployment plan that specifies the database driver, connection URL, and SQL, among other data.
Part 2 will extend the simple login system created in this article to implement a registry system where new visitors can register and immediately gain access to the system. This is accomplished by creating a Java servlet that allows users to enter their personal and login information and that stores this information in the built-in Derby database.
This article uses the Milestone 5 (M5) version of Geronimo and assumes you have no prior knowledge of Geronimo. To use Geronimo, you need Java 1.4.2_08 (or later, but before 1.5), available from the Sun Web site.
After you've installed the Java code, download Geronimo M5 from Apache. Select either the .zip (Windows or Linux) or the .tar.gz (Linux) file. When the download completes, all you need to do is decompress the .zip or .tar.gz file, and then you're ready to start the server.
You need .jar files for the SQL login module to work. They contain the IBM DB2® Java Database Connector (JDBC) Universal Drivers. Download them from IBM.com. Unzip the .zip file you get from IBM. Now take the two .jar files in the lib directory, db2jcc.jar and db2jar_license_c.jar, and place them in the <geronimo-install-dir>/repository/org.apache.derby/jars directory of your Geronimo installation.
You also need Apache Ant for this article, because it helps streamline the process of creating the .war file. Download Ant from Apache as well. After you decompress Ant, add the <ant-install-dir>/bin directory to your path.
Derby: Setting up the database
To get the concepts of the article across, a simple application (see the readme file in the zipped source file available in the Downloads section) is implemented to demonstrate logging in using J2EE declarative security and Geronimo's built-in Derby database to gain access to the system. You use the Geronimo console to set up the users and groups tables. The users tables holds username, password, e-mail, and any other user-specific information you would like to add. The groups table holds information about which groups each user is a part of. Later, Geronimo queries these tables to obtain the username and passwords to authenticate your login session and the groups you are a part of. Geronimo then matches this information with those who are allowed access and denies or allows access accordingly.
Logging into the Geronimo console
First, you create the database directly in the Geronimo console. The console allows you to look at server stats and error/message logs, and, of course, perform database management.
Pull up a Web browser, and go to http://localhost:8080/console/. Log in by entering Geronimo's default username, system, and password, manager (see Figure 1).
Figure 1. Logging in to the Geronimo console
Now that you're logged in, you should see server info, as shown in Figure 2.
Figure 2. The Geronimo console
Next you create and initialize tables in the database.
Now that you're logged in, click the DB Manager link at the bottom right of the console (see Figure 2).
This is where you enter SQL to create and initialize the user and admin tables. Enter the following SQL, as shown in Listing 1, into the Geronimo console.
Listing 1. SQL for creating and initializing the tables
create table users (username varchar(30) primary key,
email varchar(100),
password varchar(30));
insert into users values ('JohnDoe','JohnDoe@localhost','mypass');
insert into users values ('admin','root@localhost','adminpass');
insert into users values ('system','system@localhost','manager');
create table groups_users (username varchar(30),
groupname varchar(30));
insert into groups_users values ('JohnDoe','registeredUsers');
insert into groups_users values ('admin','administrators');
insert into groups_users values ('system','administrators');
|
Now click Run SQL. The following text should appear beneath the large text box, indicating success:
Result:
SQL command/s successful
This creates two tables:
- users contains user and password information. This can also contain a variety of other personal information, including origin, hobbies, and so on.
- groups_users contains user-to-group mappings needed for J2EE group-based authentication.
You used the Geronimo console to create and initialize the user and group tables. Next you define the application's security.
Your client is a big fan of J2EE security, because it is, as its name states, secure. Not only that, but it's fully supported and compatible with Geronimo. Your client is also a firm believer that authentication must be done using a database so that new users can later register and immediately log in.
The guts of the process using a SQLLoginModule as opposed to using a FilePropertiesLoginModule are very different, even though the overall process of implementing J2EE security in the "Restrict directory access with Apache Geronimo" article is more or less the same as in this article. More specifically, your deployment plan depends on database and database driver .jar files that facilitate connecting to the built-in Derby database.
Configure security using Derby
Your application needs a security deployment plan that specifies what the source is for obtaining username and password information for authenticating users. The deployment plan of your application consists of three GBeans. (See Resources for a link to more information on GBeans.) Create a file, called my-db-plan.xml, place it in the WEB-INF directory of your application, and define it as shown in Listing 2.
Listing 2: my-db-plan.xml file
<?xml version="1.0" encoding="UTF-8"?>
<configuration xmlns="http://geronimo.apache.org/xml/ns/deployment-1.0"
configId="com/ibm/geronimo/security/myDbPlan"
parentId="org/apache/geronimo/Security">
<dependency>
<uri>org.apache.derby/jars/db2jcc.jar</uri>
</dependency>
<dependency>
<uri>org.apache.derby/jars/db2jcc_license_c.jar</uri>
</dependency>
<dependency>
<uri>org.apache.derby/jars/derbynet-10.1.1.0.jar</uri>
</dependency>
<gbean name="my-sql-login"
class="org.apache.geronimo.security.jaas.LoginModuleGBean">
<attribute name="loginModuleClass">
org.apache.geronimo.security.realm.providers.SQLLoginModule
</attribute>
<attribute name="serverSide">true</attribute>
<attribute name="options">
jdbcUser=system
jdbcPassword=manager
jdbcURL=jdbc:derby:net://localhost:1527/SystemDatabase;
jdbcDriver=com.ibm.db2.jcc.DB2Driver
userSelect=select username, password from app.users
groupSelect=select groupname, username from
app.groups_users
</attribute>
<attribute name="loginDomainName">my-sql-realm</attribute>
</gbean>
<gbean name="my-sql-realm"
class="org.apache.geronimo.security.realm.GenericSecurityRealm">
<attribute name="realmName">my-sql-realm</attribute>
<reference name="LoginModuleConfiguration">
<name>my-sql-login</name>
</reference>
<reference name="ServerInfo">
<module>org/apache/geronimo/System</module>
<name>ServerInfo</name>
</reference>
<reference name="LoginService">
<module>org/apache/geronimo/Security</module>
<name>JaasLoginService</name>
</reference>
</gbean>
<gbean name="my-sql-login"
class="org.apache.geronimo.security.jaas.JaasLoginModuleUse">
<attribute name="controlFlag">REQUIRED</attribute>
<reference name="LoginModule">
<name>my-sql-login</name>
</reference>
</gbean>
</configuration>
|
The items of interest are in bold. The first, the configId, is important later when you extend this module in the geronimo-web.xml file. Next, you define the dependencies of your deployment plan. Your deployment plan uses these .jar files to perform the database-specific tasks defined in the first GBean, the LoginModuleGBean. This GBean specifies the login module, SQLLoginModule, which means a database is going to be used to retrieve usernames and passwords. Next there are six JDBC identifiers. These identifiers define how to connect to the database using the standard JDBC protocol to connect to databases in the Java language. Here's an explanation about the purpose of each one:
jdbcUserdefines the username to connect to the database.jdbcPasswordis the password to connect to the database.jdbcURLis the database "connect" URL.jdbcDriveris the driver used to connect to the database.userSelectis the SQL that gets executed to retrieve the usernames and passwords from the database.groupSelectis the SQL that gets executed to retrieve the groupnames and associated usernames from the database.
Next, the domain, or realm, is defined in loginDomainName, which references the GenericSecurityRealm GBean. The GenericSecurityRealm GBean names itself, my-sql-realm, and it links itself to the configuration JaasLoginModuleUse GBean. This configuration GBean specifies properties and behaviors of the login, and links itself with the first, LoginModuleGBean. Thus there are three GBeans that work together when authenticating a user's login credentials.
Next, you define security specific to your application.
Define security configurations
The web.xml file can define a number of things, and for the purposes of your company, Web Apps Corp., it defines two security-roles, two security-constraints, and a login-config. Create a file, called web.xml, place it in the WEB-INF directory of your application, and define it as shown in Listing 3.
Listing 3. web.xml file
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">
<security-role>
<role-name>registered-users</role-name>
</security-role>
<security-role>
<role-name>administrators</role-name>
</security-role>
<security-constraint>
<web-resource-collection>
<web-resource-name>Registered Users</web-resource-name>
<url-pattern>/users/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>registered-users</role-name>
<role-name>administrators</role-name>
</auth-constraint>
</security-constraint>
<security-constraint>
<web-resource-collection>
<web-resource-name>Administrators Only!</web-resource-name>
<url-pattern>/admin/*</url-pattern>
</web-resource-collection>
<auth-constraint>
<role-name>administrators</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>FORM</auth-method>
<realm-name>Jetty Realm</realm-name>
<form-login-config>
<form-login-page>/login/login.html</form-login-page>
<form-error-page>/login/loginError.html</form-error-page>
</form-login-config>
</login-config>
</web-app>
|
Define who belongs to what role
The geronimo-web.xml file defines Geronimo-specific parts of the J2EE security process. Create a file, called geronimo-web.xml, place it in the WEB-INF directory of your application, and define it as shown in Listing 4.
Listing 4. geronimo-web.xml file
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="http://geronimo.apache.org/xml/ns/j2ee/web-1.0"
xmlns:sec="http://geronimo.apache.org/xml/ns/security-1.0"
configId="com/ibm/geronimo/security/myDbApp"
parentId="com/ibm/geronimo/security/myDbPlan">
<context-root>/sqlSecurityDemo</context-root>
<context-priority-classloader>false</context-priority-classloader>
<security-realm-name>my-sql-realm</security-realm-name>
<security>
<default-principal realm-name="my-sql-realm">
<principal class=
"org.apache.geronimo.security.realm.providers.GeronimoUserPrincipal"
name="nobody"/>
</default-principal>
<role-mappings>
<role role-name="registered-users">
<realm realm-name="my-sql-realm">
<principal class=
"org.apache.geronimo.security.realm.providers.GeronimoGroupPrincipal"
name="registeredUsers" designated-run-as="true"/>
</realm>
</role>
<role role-name="administrators">
<realm realm-name="my-sql-realm">
<principal class=
"org.apache.geronimo.security.realm.providers.GeronimoUserPrincipal"
name="system"/>
<principal class=
"org.apache.geronimo.security.realm.providers.GeronimoUserPrincipal"
name="admin"/>
</realm>
</role>
</role-mappings>
</security>
</web-app>
|
The items of interest are in bold. The first two are the configId and parentId of your application. Notice that parentId equals the configId specified in the my-db-plan.xml file. This is because the my-db-plan.xml is the deployment plan of your application and will fail to deploy on Geronimo without it. The next item, context-root, specifies what directory, in the context of the root directory, your application can be found on in Geronimo after it has been deployed. The security-realm-name specifies the name of the realm that can/will be referenced within the geronimo-web.xml file. Then there are two role-mappings. The first one adds users in the registeredUsers group to the registered-users role in the context of my-sql-realm, defined in my-db-plan.xml. The next one adds two users, system and admin, as members of the administrators role, also in the context of my-sql-realm.
Now you're ready to build the application. Edit the build.properties file, and replace the java.home variable with the path to your Java distribution:
java.home=c:/j2sdk1.4.2_09
Now you can build the .war file by typing ant.
The .war file is now created and named security.war. Next you deploy and test your application on the Geronimo application server.
To test your application, you first deploy the security deployment plan for your application, as defined in my-db-plan.xml, then you deploy your application. With your application's deployment plan and your application deployed on Geronimo, you test the security of your application and verify that the registered-users and administrators roles, defined previously, function as defined. Unlike the way you tested the application in the "Restrict directory access in Apache Geronimo" article, here you want to test that your application is successfully authenticating through Geronimo's built-in Derby database.
Deploy your application's deployment plan
Deploying your application's security deployment plan to Geronimo allows your application to connect to it later. Go to the root directory of your Geronimo installation in a new console window. Type the following to deploy your my-db-plan.xml file:
java -jar bin/deployer.jar --user system --password manager
deploy ../secDbApp/WEB-INF/my-db-plan.xml
This command deploys your application's security deployment plan to Geronimo. Geronimo indicates a successful deployment by outputting:
Deployed com/ibm/geronimo/security/myDbPlan
Recall that the parentId of your application, as defined in the geronimo-web.xml file, is just that: com/ibm/geronimo/security/myDbPlan.
Now you can deploy your application the same way you did the deployment plan. Typing the following deploys your application on Geronimo:
java -jar bin/deployer.jar --user system --password manager
deploy ../secDbApp/security.war
If you did not first deploy your application's security deployment plan previously, your application will fail to deploy here. Upon deploying your application, Geronimo looks for an installed module with configId equal to the parentId of your application, as defined in geronimo-web.xml. It finds the parentId, com/ibm/geronimo/security/myDbPlan, which you have already deployed, and continues deploying your application.
You have now deployed your application on Geronimo. Geronimo lets you know your deployment is successful by outputting the following:
Deployed com/ibm/geronimo/security/myDbApp @
http://your-a9279112e3:8080/sqlSecurityDemo
The application is deployed and ready for testing, which you do next.
Test the registered-users role
You test your application by visiting the Web site you just created. Open a Web browser, and point it to the URL http://localhost:8080/sqlSecurityDemo/.
The main page should now load. Click the user's login link, which loads the login page. Enter a username, JohnDoe, with password, mypass, which you inserted into the database in Listing 1. See Figure 3.
Figure 3. Logging in to the users area
The password is contained in the database. Upon successful verification, the user is redirected to the users area page.
Now try visiting the admin page. Click the link to return to the main page, and then click the Administrators login here link. Example output is shown in Figure 4.
Figure 4. Access denied
JohnDoe has authentication to go to the users area but not the admin area, because he isn't a member of the administrators role, as defined in geronimo-web.xml. He's a member of the registered-users role only, specified by JohnDoe's corresponding entry in the groups_users table. The database authentication is working!
Next, you test the administrators role.
Before testing the administrators role, you need to reset the login data stored on Geronimo from testing the registered-users role. Do this by closing and reopening your browser. Now click the Administrators login here link as before, except this time the login page should appear; if not, try reloading/refreshing your Web browser, because old cached data might display. This time, log in using the admin username and the adminpass password (see Figure 5).
Figure 5. Logging in to the admin area
The admin page should load. Go back to the main page, and try visiting the users area. The users area should also load normally, because the users area grants access to both administrators and registered users. Because admin is a member of the administrators role, as defined in geronimo-web.xml, you can visit both the user and admin area as this user.
You created and initialized the users and groups tables in Geronimo through the console, which initialized the database, so that you would have user names with passwords and associated groups to test your application. You also implemented declarative J2EE security using Geronimo's built-in Derby database as the source for authenticating valid usernames and passwords to grant access to user-specific content on your Web site. In Part 2 of this series, you'll extend the application to include a registry system where new users can register on the Web site and immediately gain access to your client's forum.
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample code for Part 1 | dbsecurity1.zip | 8KB | HTTP |
Information about download methods
Learn
- Learn more about GBeans in the article "Integrate third-party components into Geronimo" (developerWorks, August 2005).
- Read "Restrict directory access in Apache Geronimo" (developerWorks, November 2005) to learn how to implement Geronimo security by storing usernames and passwords in files rather than in a database.
- Find valuable resources in the "Get started now with Apache Geronimo" section of developerWorks.
- Read "Build a secure enterprise infrastructure with Geronimo" (developerWorks, July 2005) for a broad survey of security topics.
- For more great pieces on Geronimo, check out the following content:
- "Building a better J2EE server, the open source way" (developerWorks, May 2005)
- "Geronimo! Part 1: The J2EE 1.4 engine that could" (developerWorks, May 2005)
- "Geronimo! Part 2: Tame this J2EE 1.4 bronco" (developerWorks, May 2005)
- "Three ways to connect a database to a Geronimo application server" (developerWorks, June 2005)
- "Create, deploy, and debug Apache Geronimo applications" (developerWorks, May 2005)
- "Apache Geronimo uncovered" (developerWorks, August 2005)
Get products and technologies
- Download your free copy of IBM WebSphere® Application Server Community Edition V1.0 -- a lightweight J2EE application server built on Apache Geronimo open source technology that is designed to help you accelerate your development and deployment efforts.
- Explore the IBM Support for Apache Geronimo offering for expert technical support in developing your Apache Geronimo applications.
Discuss
Tyler Anderson graduated with a degree in Computer Science from Brigham Young University in 2004 and is currently in his last semester as a Master of Science student in Computer Engineering. In the past, he worked as a database programmer for DPMG.COM, and he is currently an engineer for Stexar Corp., based in Beaverton, Oregon.




