Application Management
Developing Standalone Client Applications
In a secure WebSphere 5 environment
Feb. 23, 2005 12:00 AM
In an enterprise WebSphere 5.1 deployment, the application business logic is developed as Enterprise JavaBeans (EJB). In many situations, there exists a need to execute standalone Java programs that run outside the container. To reuse the business logic present in the EJBs, the application client can use the EJB resources that are provided by the application server. However, in an enterprise deployment, these resources are protected from external use by a security system that requires clients to present appropriate credentials to access any of the application server resources. This article describes the programming model as well as the client and server configurations needed to develop a Java thin client application.
Programming Model
In order to connect to WebSphere Application Server 5.1 in a secured environment using an RMI/IIOP connection, an application needs to perform certain operations in a particular order. These operations are:
- Initialize the Object Request Broker (ORB) inside the client JVM
- Log into the application server providing the appropriate credentials
- Asserting the identity of requester, obtain a reference to the appropriate resource
- Execute the operations on the resource
This section describes these operations, their order, and the reason for executions.
Initialize the Object Request Broker
The first operation in the scheme above is to initialize the Object Request Broker. This is done by creating an InitialContext object passing in the information about the location of the target application server and the name of the InitalContextFactory implementation class. After performing an InitialContext creation, perform a default lookup so that the bootstrap host/port can be determined for the security server lookup.
Hashtable env = new Hashtable(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.ibm.websphere.naming.WsnInitialContextFactory"); env.put(Context.PROVIDER_URL, "corbaloc:iiop:myhost.mycompany.com:2809"); Context initialContext = new InitialContext(env); Object obj = initialContext.lookup("");
If the target server is located at the same machine as the client, we do not need to specify the Context.PROVIDER_URL in the hashtable. If the target server is running on a remote machine, or if it is running on the same machine as the client but the IIOP listener port is not 2809, we have to provide that information to the InitialContext. In this situation, perform a new InitialContext programmatically ahead of the JAAS login. JAAS needs to know where the Security Server resides to verify that the user ID or password entered is correct prior to doing a commit(). By performing a new InitialContext in this way, the security code has the information needed to find the Security Server location. This can be performed in the following ways:
- Define a system variable java.naming.provider.url at the command line and set its value to the IIOP URL of the target WebSphere application server
java -Djava.naming.provider.url=corbaloc:iiop:myhost.mycompany.com:2809 -Djava.naming.factory.initial=com.ibm.websphere.naming.WsnInitialContextFactory
- Create a file named jndi.properties and place the file in the class path of the client JVM. The file will contain the following information:
java.naming.provider.url=corbaloc:iiop:myhost.mycompany.com:2809 java.naming.factory.initial=com.ibm.websphere.naming.WsnInitialContextFactory
- Provide it to the constructor of the InitialContext as shown in the example above
In a WebSphere 5.1 cell, the URL can point to any WebSphere application server running inside the cell. Since this initial context is only used to initialize the ORB running inside the client JVM, and no contact with the application server is made, we do not need to provide the credential during the creation of the InitialContext here.
Perform a JAAS Programmatic Login
A secured enterprise bean application requires the identity of the user that is looking up the EJB and invoking the method for authentication and authorization purposes. This information has to be collected in the client application and provided to the user. There are two different models for performing this, batch programs and user interactive programs.
Batch Programs
These are standalone programs that run without user interaction and use one identity to perform all the operations. In this case, the information can be provided statically in the sas.client.props properties file. The application client will then be written in such a way that the runtime uses this information rather than collecting from the user. In order to perform this mode of authentication, the following properties must be specified in the sas.client.props file:
loginSource: This specifies how the credentials for user validations are obtained. For batch programs this value should be set to properties or keyfile. If set to properties, the value for the username and password are specified in this file as mentioned below. If the value is keyfile, then the username and password can be specified in a keyfile.
com.ibm.CORBA.loginSource=properties
loginUserid: This specifies the username to be used to authenticate the client code and it will be the identity of the caller for EJB authorization checks on the application server. This must be specified in conjunction with the loginSource set to properties above.
com.ibm.CORBA.loginUserid=wasadmin
loginPassword: This specifies the password for the username specified above
com.ibm.CORBA.loginPassword=wasadminpassword
After initializing the ORB (as specified above), the application can be written in a normal way. At locations where the client looks up the EJB resources, the application server will challenge the client for authentication information. This information will be gathered by the client runtime from the sas.client.props and passed onto the application server. The code in Listing 1 depicts this model.
The component of the test application in Listing 1 that accesses EJBs is shown to run both in a separate thread and the main thread. Test is an EJB that has authorization rules defined using declarative security.
User Interactive Programs
As opposed to the batch programs, user interactive programs collect the authentication information from the user. The client application then runs using the identity of that user. In this case, providing the authentication information inside the sas.client.props will not suffice. For this model, there are two options:
- Use the WebSphere default information collection mechanism. WebSphere provides two user interfaces that can be used to collect the username and password from the user.
a. GUI: This is a basic Swing window that prompts the user to specify the username and password.
b. Stdin: This is the command line standard input.
Using this model, the application can be written in exactly the same way as the batch programs above. No special programming is needed except initializing the Object Request Broker.
- Provide your own user interface and own the responsibility of collecting this authentication information and then use that information to programmatically log onto the application server. Once the authenticated Java subject is obtained from the logging in process, it is used to execute the actions that require access to the EJB resource on the application server (see Listing 2). (Listings 2 and 3 can be downloaded from sys-con.com/websphere/sourcec.cfm.) Additionally, the application can create an implementation of the CallbackHandler interface that creates the user interface to collect the information from the user.
To execute Listing 2 the sas.client.props would need to be modified to contain the following.
com.ibm.CORBA.loginSource=none
The things to note in this programming model are:
- CallbackHandler: A CallbackHandler is a JAAS mechanism to collect authentication information from the user. Since we are taking up the responsibility of collecting that information using our custom interface, we will be using a nonuser interactive WebSphere CallbackHandler implementation:
com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl
We can also use the following CallbackHandler:
* com.ibm.websphere.security.auth.callback.WSGUICallbackHandlerImpl
* com.ibm.websphere.security.auth.callback.WSStdinCallbackHandlerImp
These two CallbackHandler implementations will produce a user interface identical to the GUI and Stdin interfaces discussed previously. In the sample code above, reflection has been used to create the CallbackHandler. The benefit of this is that you would not need to place that class in your build classpath. When the application runs (configured as shown in the next section), the runtime shall provide the definition of the class. The developer can choose to use the two-parameter constructor to create an object of that class.
- LoginContext: A LoginContext is a vehicle in the JAAS mechanism to specify the Login Module alias (client application should use "ClientContainer" login module) and the CallbackHandler. The LoginContext is used to login, which in the background invokes the CallbackHandler to collect the authentication information. It then passes this information to the login modules that are specified using the alias.
- Login action: Creates a subject that contains the principles corresponding to the logged in user.
- WSSubject.doAs(): In order to associate the current thread's identity with the authenticated procedure, the doAs method on the WebSphere WSSubject is invoked.
- PrivilegedAction: The code to access the EJB resources on the application server should be wrapped inside the run method of a class that implements PrivilegedAction. The code running inside this block is associated with the identity of the subject passed into WSSubject.doAs().
- Thread: If your client application creates threads, the client JVM runtime does not propagate the thread identity to the newly created thread. Therefore, your application will need to make sure that the authenticated subject is available to each thread, if that thread looks up EJB resources on the application server.
Running the Client Application
In order to start and run the thin Java application client there are several settings that need to be provided to the Java runtime at the command line. Listing 3 shows a sample batch file that launches the TestJavaThinClient class.
The following items need to be noted about the patch file:
- JVM: In order to use Java thin clients, we have to use the IBM JRE. The runtime that has been used in this example is from the WebSphere application client. The runtime that comes with WebSphere Application Server can be used instead.
- Classpath: The Client JVM uses hierarchical class loaders to load all the relevant classes. There are three class loaders involved.
a. Extension class loader: The classpath for this class loader is specified through the value of java.ext.dirs on the command line. This should contain the JRE extention classes as well as all the IBM WebSphere specific classes. If your application used JMS, then this is the location where you would put JMS specific jars.
b. Bootstrap class loader: The classpath for this class loader is specified using the -Xbootclasspath/p: syntax on the classpath. This will contain the ibmorb.jar and the WebSphere properties.
c. Application class loader: All the client application classes, utility JARs, and EJB client JARs are specified in this classpath. This is specified using the -class path syntax on the command line.
- SAS client file: The location to the SAS client file is specified using com.ibm.CORBA.ConfigURL parameter on the command line. This URL points to the sas.client.props file.
- STDIN cLIENT SAS: This is a SAS client file where the login source has been set to standard input.
- SOAP client file: The location of the SOAP client file is specified using the com.ibm.SOAP.ConfigURL parameter on the command line. This URL points to the soap.client.props. The properties in this file dictate the SOAP communication between the application client and the application server. The client can make JMX administrative calls to the application server using the SOAP connector. This file dictates the security settings for that communication. If your application does not make any JMX administrative calls, you can point this to the default soap.client.props file located under the WebSphere/properties folder.
- JAAS login configuration: The location to the JAAS login configuration file is specified using the java.security.auth.login.config. This file specifies the login modules for the JAAS login alias ('ClientContainer') that were used in our application.
Summary
To write a Java thin client to access EJB resources on an application server certain programming models and configurations need to be specified. This article discussed a few of these programming models and mentioned the property settings needed to configure the client JVM to successfully make the remote calls to a secured application server.