HomeDigital EditionSys-Con RadioSearch Java Cd
Advanced Java AWT Book Reviews/Excerpts Client Server Corba Editorials Embedded Java Enterprise Java IDE's Industry Watch Integration Interviews Java Applet Java & Databases Java & Web Services Java Fundamentals Java Native Interface Java Servlets Java Beans J2ME Libraries .NET Object Orientation Observations/IMHO Product Reviews Scalability & Performance Security Server Side Source Code Straight Talking Swing Threads Using Java with others Wireless XML
 

Implementing J2EE Security With WebLogic Server, by Jason Westra and Chris Siemback

In the March issue of JDJ (Vol. 6, issue 3) we discussed the basics behind J2EE security, including coverage of role-based security for both the Web and EJB tiers. In Part 2, we provide an example of implementing J2EE security in the WebLogic Server.

While this article and the examples contained within are specific to WebLogic 6.0, all of the deployment code and standard descriptors should be portable to any J2EE-compliant server. We won't cover encryption and SSL this month, as they're articles in their own right.

Trader Application
How many securities trading examples have you seen to date? Too many, I bet you'd say. Well, we decided airline reservation systems and "hello, world" programs are way too overused. Even though the stock market is not a hot topic these days, in an effort to spend more time explaining J2EE security and less time talking about business requirements, we opted for the trading program as well.

The application we'll be building represents a stock trading system in which users may buy, sell, and view securities. We'll grant all paying customers the ability to purchase and view securities. However, we'll reserve the ability to sell securities to just traders, who may also view and purchase securities. Basically, traders are the power users of our system! Furthermore, we'll provide a customized login page that can be tailored to the look and feel of our site rather than relying on a basic browser authentication window.

To build our application we've chosen the WebLogic Server 6.0. With WebLogic 6.0, we'll take advantage of features such as a security domain based on a relational database, Web application security, and method-level EJB security.

Implementing J2EE Security with the WebLogic 6.0 Server
There are several things we'll need to accomplish to get our end-to-end application up and running with the security constraints we require. Listed below are the basic steps for creating and implementing this functional example:

  1. Configure a security domain
  2. Secure the Web tier
  3. Secure the EJB tier
  4. Demonstrate end-to-end security in a J2EE application
Configure a Security Domain
Before we can secure anything, we must have a security domain that contains our users and groups. WebLogic Server provides several methods to construct and use security domains (or realms). The default WebLogic domain is file-based, storing users, groups, and ACLs (access control lists) for the server in separate properties files. The file-based domain is easy to read and configure in the server, but it's not a scalable solution for an organization with any real user-base. The File Realm solution is designed for systems with 1,000 or fewer users. Furthermore, if the file itself becomes corrupt, you'll need to reconfigure security again. This is unacceptable in an enterprise-level application, which must have a robust, scalable security domain.

WebLogic provides plug-in capabilities for more scalable solutions including LDAP, UNIX, and NT security. In this example, we'll use the RDBMSRealm that comes with the standard WebLogic install. This plug-in domain uses a relational database to store security information. The RDBMSRealm is easy to use, offers configurable caching of security information, and refreshes its data without downtime - features we're particularly interested in exploiting for our production J2EE application. So, how easy is it? Let's see.

Our first step in configuring a security domain is to create the relational tables necessary to store our information. The RDBMSRealm consists of three database tables: USERS, GROUPMEMBERS, and ACLENTRIES. WebLogic provides the DDL (data definition language) necessary to create the tables in a file called rdbmsrealm.ddl. Use the WebLogic utility, utils.Schema, to run the DDL or create the tables by hand. This file will also insert some sample data entries in each of the three tables to ensure that we understand the format of the data that's expected by the domain's tables. Note: You may need to modify the scripts to work with your particular database or the default data that's being inserted - but changing table or column names will force you to make some modifications to the schema properties (described later). We advise just using the schema provided for your initial look into the security example.

For our example we're creating two groups, onlineinvestor and trader. Once the database tables have been created, we can create and register the domain for use within WebLogic.

After creating our domain tables, we need to ensure our security domain classes are built and available to the WebLogic Server. Again, we're using the example security classes provided by WebLogic. You'll find the security classes in the following directory:

/WEBLOGIC_HOME/samples/examples/security/rdbmsrealm

They'll need to be compiled and put in the server classpath for the domain to function properly.

Enable the Domain for WebLogic
The RDBMSRealm relies on properties contained within the config.xml file used for your domain for the database connection information and on the SQL statements that will be used with such actions as adding or deleting users and groups. To create the RDBMSRealm, you should launch the WebLogic Server Console. The WebLogic Server Console is a Web-based administrative utility that allows developers to remotely manage nearly all the facets of the WebLogic Server. It's a welcome upgrade from previous versions of this tool. To enable the domain, we simply select the "Realms" node located under "Security" (see Figure 1). You'll need to follow the "Create a new RDBMSRealm" link and enter the appropriate information. For this example, we've chosen to name our domain "JDJDomain" and we've also provided the fully qualified class name of the RDBMSRealm (examples.security.rdbmsrealm.RDBMSRealm).

figure 1
Figure 1:  WebLogic console

Now that we have the domain defined, we must provide WebLogic with the database connection information that's required to access the database. To do this, click on the "Database" tab and enter the appropriate information for the connection. An example of this is shown in Figure 2.

figure 2
Figure 2:  Database configuration

After you've entered the appropriate data, click on the "Apply" button. Now that we've constructed our domain and supplied WebLogic with the necessary connection information, we must provide some additional properties that our Domain classes will use to manipulate the data. The schema properties are the values for the PreparedStatements that the RDBMSDelegate uses to make modifications to the data store. After selecting the "Schema" tab and entering the appropriate properties, we can apply them.

Now that we've completed the domain, we need to select the "Caching Realms" and create a new Caching Realm, selecting the "JDJDomain" that we just created from the drop-down list box. We have the option of modifying the caching properties, which will affect the performance of our security domain.

Last, we need to select the Caching Realm we just created from the drop-down list box under the "Security" node. Once we restart the server, we should be ready to rock and roll!

Securing the Web Tier
With the Servlet 2.2 specification, J2EE application deployers and system administrators have the ability to apply declarative security to Web content. This method of security is portable to any J2EE-compliant server and allows developers to define custom login and error pages. In fact, we can assign custom error pages for specific Java exceptions and HTTP codes (e.g., 404 page not found error) so we can hide the error behind a nice message such as, "We are currently experiencing high volume. If you are a venture capitalist looking to fund us, please forward money to account XYZ. Thank you."

Create Web Deployment Descriptors
To apply security at the Web tier, we edit the Web application's standard, web.xml, and WebLogic's proprietary WebLogic.xml deployment descriptors to define the Web resources, security restrictions, a custom login page, and error page. Both the web.xml and WebLogic.xml files are located within the WEB-INF directory in the HTML document root. Breathe easy, security-mongers.... This directory is not accessible to browsers, even though it's contained within the HTML root.

The web.xml file (see Listing 1) is the standard Web application deployment descriptor. It defines a Web application's Web resources, essentially a collection of pages, and their attached security constraints. Also, we've defined a custom login page when users need to be authenticated. When users first hit a restricted page, the custom login page is presented to them. If the user is authenticated and granted access, the user is automatically brought to the page he or she was originally intended to get to. If authentication fails or the user doesn't have access to the page, then he or she is brought to the form-error page. With this method, developers don't have to explicitly carry and insert the user's credentials or security attributes, a J2EE server such as WebLogic 6.0 handles this functionality for you.

After defining the web.xml file, we need a corresponding WebLogic Web descriptor, called WebLogic.xml appropriately enough. This file is proprietary and is used to link external references such as security principals from the standard web.xml descriptor to our deployment environment in the WebLogic Server. Listing 2 provides an example of the WebLogic.xml file that we'll use. Notice how generic role descriptions in the web.xml such as "role-onlineinvestor" is mapped to onlineinvestor, an actual principal in our security domain. This mapping is expressed visually in Figure 3.

figure 3
Figure 3:  Mapping security attributes

Construct a Custom Login Page
Now that we have our Web security defined in our descriptors, we need to construct the login.jsp page we defined in the web.xml file. This file allows us to construct a login page that doesn't rely on the browser's native authentication method and enables us to design the page to look like the rest of our site. The requirements for this page are explained in detail in the Servlet 2.2 specification, but let's briefly cover the basic ones here.

Listing 3 is the most basic login JSP we can create. In this page, we have a form that will send user credentials to the server. The form ACTION attribute must be set to "j_security_check". We also require two text fields to contain the username and password. They're required to have the attribute value of NAME equal to "j_username" and "j_password" respectively. These naming conventions allow the Web container that's servicing an authentication request to handle it generically.

The login.jsp works like this: when users first attempt to access a restricted Web resource, the request is sent to the container, which stores the URL of the request and sends back the login form. The user then inputs his or her credentials and submits the form back to the container. If the user has valid permissions, he or she is brought to the URL that was originally requested. If the login fails, the user is brought to the login-error page.

Securing the EJB Tier
Now that we have a working security domain and have successfully secured our Web tier, let's add security to our TraderEJB in the EJB tier. Even though we have Web-tier security, since EJBs are remote objects they may be accessed from clients other than a Web server. For this purpose, we want to also apply restrictions on our EJB methods.

To do so we can modify our TraderEJB component to implement the security restrictions specified by our application requirements.

J2EE security is designed as a container-based service and set at the thread level, which enables the context to be propagated to other components on subsequent calls. This feature simplifies the security of J2EE applications by implicitly passing the security context of the user to each component without requiring the developer to code security logic. Security constraints can be added, removed, or updated without affecting the components that utilize the container's security services. Since J2EE security is declarative, we need only update XML descriptors to secure the TraderEJB.

Table 1 describes the security restrictions placed on the TraderEJB's methods in the XML descriptors. For demonstration purposes, these methods are hard-coded; however, in a real application, these methods would probably access a real-time quote feed for securities, and store shares bought and sold with JDBC or entity beans.

table 1
Table 1:  Security resource to role mapppings

The Web tier doesn't have to authenticate a user until a secured Web resource is requested. At some point the Web tier may contact an EJB even if a user has never been established; however, the EJB tier must have a user. To solve this dilemma, the J2EE specification requires that a J2EE product supply a principal in place of the empty user. WebLogic defines the group everyone and the users guest and system to support this functionality. Because they're inherent in WebLogic, they don't need to be defined in the RDBMSRealm.

The ejb-jar.xml file (see Listing 4) is where we assign permissions to methods in the EJB. From within the method-permission tag we define which roles have access to which methods. For example, we've added the role-onlineinvestor and role-trader (which map to the onlineinvestor and trader groups, respectively, in the domain) to the buy method. You may add as many groups as necessary to the method's permission. For the sell method, we've allowed only the trader group. The last method, getSecurities, provides permission to the implicit everyone group. Remember that J2EE security allows access to restricted methods as long as the user is in at least one of the groups defined.

The WebLogic-ejb-jar.xml file (see Listing 5) maps the actual group/user name contained within the domain to a role name that's used within the XML files. Here we're assigning a role-name, which will be used in the ejb-jar.xml, to the actual principal name contained within the database domain. We're currently mapping the trader group to the role-name role-trader. The same is true for the onlineinvestor and everyone.

How Did We Do?
We now believe we have a functional application that meets the security requirements stated. Let's test our application to be sure. Where do we begin? Since we defined in the web.xml that only the /trade/index.jsp page should have security, we should be able to freely access any other portions of our site without being prompted for authentication. It's pretty simple testing security when there really isn't any!

Now, let's attempt to access resources that are reserved for online investors and traders. Since we've secured access to the resources in the trade directory, we should get sent to the custom login page we created when we access these pages. Enter the credentials for an onlineinvestor, and we should get forwarded back to the page we were attempting to access in the first place. Now, we should be able to list and purchase securities. So far, so good.

Last, let's attempt to access these resources as a trader. To be safe, let's close our browser and then access the restricted pages again, logging in as a trader this time. We should now be able to perform all three of the EJB methods that we've secured, including selling securities. Note: If we had originally logged in as a trader, we would not have been prompted again unless we tried to access resources traders don't have access to.

Understanding WebLogic's Security Exceptions
As stated in Part 1, there are two steps involved when the user attempts to access a controlled resource, authentication, and authorization. First, WebLogic authenticates the user by determining whether the specific user even exists in the domain. If the user isn't present, an Authentication-Exception is thrown.

If the user exists, WebLogic checks the permissions to determine if the user has authorization to access a service. If the user is authorized, the service is accessible and methods may be executed. Table 2 lists the possible exceptions that can be thrown when checking security access.

table 2
Table 2:  WebLogic security exception details

Conclusion
This month we took the basic J2ee security knowledge we learned in our last column and applied it toward a working example on the WebLogic Server's implementation. Specifically, our example was based on WebLogic's RDBMSRealm, a security domain that utilizes a relational database to store its information. We hope this month's EJB Home improved your comfort level with J2EE security and enlightened you on its benefits and ease of use when applying it through the WebLogic Server.

Author Bios Jason Westra is CTO at Verge Technologies Group, Inc., a Java consulting firm specializing in e-business solutions with Enterprise JavaBeans. He can be contacted at [email protected]

Chris Siemback, an Enterprise Java consultant at Verge Technologies Group, Inc., specializes in Web-based EJB applications, various development methodologies, and distributed architectures. He can be contacted at [email protected]

	


Listing 1: web.xml
 
 <security-constraint> 
    <web-resource-collection> 
      <web-resource-name>TradeApp</web-resource-name> 
            <url-pattern>/trade/*</url-pattern> 
      <http-method>POST</http-method> 
      <http-method>GET</http-method> 
    </web-resource-collection> 
    <auth-constraint> 
      <role-name>role-onlineinvestor</role-name> 

    </auth-constraint> 
  </security-constraint> 

   <login-config> 
        <auth-method>FORM</auth-method> 
        <domain-name>JDJDomain</domain-name> 
        <form-login-config> 
                <form-login-page>/jsp/login.jsp</ 
                   form-login-page> 
                <form-error-page>/jsp/loginerror.jsp</ 
                   form-error-page> 
        </form-login-config> 
  </login-config> 

  <security-role> 
       <description>the customer role</description> 
       <role-name>role-onlineinvestor</role-name> 
  </security-role> 

  <security-role> 
       <description>the customer role</description> 
       <role-name>role-trader</role-name> 
  </security-role> 
  
  

Listing 2: WebLogic.xml
 
<security-role-assignment> 
       <role-name>role-onlineinvestor</role-name> 
       <principal-name>onlineinvestor</principal-name> 
     </security-role-assignment> 

     <security-role-assignment> 
       <role-name>role-trader</role-name> 
       <principal-name>trader</principal-name> 
     </security-role-assignment> 
  

Listing 3: logic.jsp
 
<HTML>
<BODY> 
The page you're attempting to access is restricted, please login:
<br>
<FORM METHOD="post" ACTION="j_security_check"> 
Username: <INPUT TYPE="text" NAME="j_username"><br>
Password: <INPUT TYPE="text" NAME="j_password"><br>
<p> <INPUT TYPE="Submit" NAME="Submit" VALUE="Submit">
</FORM>
</BODY>
</HTML> 
  

Listing 4: WebLogic-ejb-jar.xml
 
                <security-role-assignment> 
         <role-name>role-onlineinvestor</role-name> 
         <principal-name>onlineinvestor</principal-name> 
   </security-role-assignment> 

   <security-role-assignment> 
         <role-name>role-trader</role-name> 
         <principal-name>trader</principal-name> 
   </security-role-assignment> 

   <security-role-assignment> 
         <role-name>role-everyone</role-name> 
         <principal-name>everyone</principal-name> 
   </security-role-assignment> 
  
  

Listing 5: ejb-jar.xml
 
<assembly-descriptor> 
     <security-role> 
         <description>Investor in the application</description> 
         <role-name>role-onlineinvestor</role-name> 
     </security-role> 
     <security-role> 
         <description>A stock broker, or trader</description> 
         <role-name>role-trader</role-name> 
     </security-role> 
     <security-role> 
         <description>Anyone in the RDBMSDomain</description> 
         <role-name>role-everyone</role-name> 
     </security-role> 
     <method-permission> 
         <description> 
         This permission gives the right to purchase shares. 
         </description> 
         <role-name>role-onlineinvestor</role-name> 
         <role-name>role-trader</role-name> 
         <method> 
              <ejb-name>jdj.security.SecureTradeMgr</ejb-name> 
              <method-name>buy</method-name> 
         </method> 
     </method-permission> 
     <method-permission> 
         <description> 
         This permission gives the right to sell shares. 
         </description> 
         <role-name>role-trader</role-name> 
         <method> 
              <ejb-name>jdj.security.SecureTradeMgr</ejb-name> 
              <method-name>sell</method-name> 
         </method> 
     </method-permission> 
     <method-permission> 
         <description> 
         This permission gives the right to view the list of 
         securities. 
         </description> 
         <role-name>role-everyone</role-name> 
         <method> 
              <ejb-name>jdj.security.SecureTradeMgr</ejb-name> 
              <method-name>getSecurities</method-name> 
         </method> 
     </method-permission> 
   </assembly-descriptor> 


  
 

Download Assoicated Source Files (Zip format ~ 9.57 KB)

 

All Rights Reserved
Copyright ©  2004 SYS-CON Media, Inc.
  E-mail: [email protected]

Java and Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. SYS-CON Publications, Inc. is independent of Sun Microsystems, Inc.