Editor's note: IBM® WebSphere® sMash and IBM WebSphere sMash Developer Edition are based on the highly acclaimed Project Zero incubator project. Project Zero is the development community for WebSphere sMash and will continue to offer developers a cost-free platform for developing applications with the latest builds, the latest features, and the support of the community.
Advanced user registry leveraging LDAP
Project Zero implements authentication and authorization. Applications can take advantage of Zero's security by defining security rules that determine which resources are protected, by what means they are protected, and what users and groups are allowed to access those resources. Zero's authentication is based on Java Authentication and Authorization Service (JAAS), which allows various types of login modules to be added without changing the authentication model.
Security is part of the core feature set included with Project Zero. Because Zero Security is a core feature, the only requirement to enable security is to properly configure the user service registry-related configuration and associate the appropriate rules for each protected resource. This article is intended for intermediate developers already familiar with Project Zero—if you need more background information or to build up your fundamental knowledge of Project Zero, see the Developer's Guide for a complete overview of Project Zero Security configuration, or read the first developerWorks article in this series, "Authentication and authorization." This article focuses on the specifics of how to configure an application leveraging security with LDAP as a user registry inside of Project Zero.
The user service is a library that provides an extensible framework for accessing user registries. Supported registry types include text file and LDAP (directory), but can be extended to create a custom user registry if that requirement exists. Your choice of registry type depends on your requirements and environment:
- Text-file registry is suitable as a development-time registry.
- LDAP is recommended for production, where enhanced reliability and security are important.
The user service is an abstraction layer between the Project Zero security runtime and the user registry, and you can choose an appropriate user registry by editing the /config/security/userservice stanza of a zero.config file.
This article shows you how to configure a user service to access an LDAP-based user registry. If you are interested in learning about the file-based user registry, take a look at Part 1, "Authentication and authorization," which provides an overview of Project Zero security leveraging the file-based user service.
Picking up where we left off...
This article will continue on from the first article, "Authentication and authorization. " The assumption is that you have already installed the appropriate Project Zero plug-ins from the Eclipse Update site and that you know how to create a Project Zero application within Eclipse. If this is not the case, refer to the Core Getting Started page of the Developer's Guide before continuing.
As described in the previous article, the application we will use is a very simple application called StockTips. The application allows for publication of very basic stock market tips. The application works by maintaining a list of "hot stocks," which have been added by and are looked after by a stock market wizard. The wizard will often add to his list when a hot new stock appears on the market, and will also remove stocks from the list when companies take a downward turn. The list is viewed by pundits—people who are interested in what the wizard has to say, and who base their stock market buying or selling decisions based on his tips. If the wizard is good with his tips, the pundits will make money.
The application code is composed of a groovy file, tips.groovy, and a view called tips.gt. Because this article is mainly focused on enabling LDAP in Project Zero, we will provide only limited screenshots of the code in this article; refer to the first article for more details. Instead we will concentrate more on the configuration required to leverage LDAP in various ways.
Since we published our first article, the wizard's stock tips site has been overwhelmed with new subscribers. Due to the immense popularity of his site and the increase in the number of pundits, the wizard has decided to move from the file-based user registry to a more enterprise-strength LDAP user registry. This will allow the application to scale from what was more of a locally used application to a more globally used application. Because we are simply migrating the users from the file-based user registry to an LDAP-based user registry, all pundits will remain part of the single group named 'pundits'.
Migrating from file-based user service to LDAP user service
Before looking into LDAP user service configuration, we should prepare a directory in
an LDAP directory server. We will use the simple directory as shown in Figure 1 for the first example. Ten users belong to the group 'pundits'
(see Table 1), and a special user named 'wizard' is a member of
'wizards'. To create the directory, you must create the root suffix dc=myco,dc=com in the LDAP directory server, and then download and import the LDAP Data Interchange Format (LDIF) file, myco.startingpoint.ldif, from the Download section to the LDAP directory server. (Refer to the manual of your LDAP directory server about creation of the root suffix as that depends on the LDAP server implementation.) To import LDIF files, you can use LDAP tools including Apache Directory studio, JXplorer, and so on. (See Resources for links to these download sites.) The LDAP user service does not depend on any specific LDAP directory servers and tools.
Each element in an LDAP directory can be identified by a relative distinguished name (RDN), which must be unique in siblings underneath a subtree. In addition, each element has a distinguished name (DN). A DN is what concatenates all RDNs from a leaf element to a root and must be unique in a whole directory. A DN is, by definition, a fully qualified name in an LDAP directory. For example, uid=mary,ou=people,o=hq,dc=myco,dc=com is a DN and its prefix, uid=mary, is an RDN. You can learn about LDAP in more detail on the IETF Web site (see Resources).
Table 1. Mapping between users and groups in the starting directory sample

By default, the LDAP user service regards an entry typed with the object class netOrgPerson as a user entry; a value of the attribute uid as a user name; an entry typed with the object class groupOfUniqueNames as a group; and a value of the attribute cn as a group name. The LDIF file myco.startingpoint.ldif included in the Download section defines:
- Ten user names and passwords that are defined underneath
ou=people,o=hq,dc=myco,dc=comand are members of the group 'pundits'.- mary for a user name and mary_pwd for a password
- dan for a user name and dan_pwd for a password
- ryan for a user name and ryan_pwd for a password
- baxter for a user name and baxter_pwd for a password
- bob for a user name and bob_pwd for a password
- steve for a user name and steve_pwd for a password
- tim for a user name and tim_pwd for a password
- john for a user name and john_pwd for a password
- ken for a user name and ken_pwd for a password
- michael for a user name and michael_pwd for a password
- The special user 'wizard' also underneath
ou=people,o=hq,dc=myco,dc=com, but a member of the group 'wizards'.- wizard for a user name and wizard_pwd for a password
Figure 1. Starting point directory sample

The zero.config is a text file storing the core configuration of Project Zero, located underneath <approot>/config. To enable Zero's security to authenticate requests with the LDAP directory, you must add a configuration stanza under "/config/security/userservice" to zero.config (as shown in Listing 1).
Listing 1. zero.config snippet—User service configuration for the simple directory sample
/config/security/userservice/registryType="ldap"
/config/security/userservice/ldap += {
"jndiProviderUrl":"ldap://localhost:10389/",
"jndiSecurityPrincipal":"uid=admin,ou=system",
"jndiSecurityCredentials":"<xor>LDo8LTor",
"ldapUserIdRdnPattern":"uid={0}",
"ldapUserIdBaseDn":"ou=people,o=hq,dc=myco,dc=com",
"ldapGroupBaseDn":"ou=group,o=hq,dc=myco,dc=com"
}
|
Following is a breakdown of Listing 1:
registryTypeis the parameter specifying which user service is used; we have set "ldap" to use the LDAP user service.jndiProviderUrlis the property for a URL of an LDAP directory server; in this case the LDAP server is running on the machine "localhost" on port 10389.jndiSecurityPrincipaldefines a principal (username) to be used to connect to the directory server; our principal is calleduid=admin,ou=system.jndiSecurityCredentialsdefines the credentials (password) to be used to connect to the directory server; our password is the xor encoded valueLDo8LTor.ldapUserIdRdnPatternspecifies an RDN template pattern used for looking up users in the directory server. The user service fills the placeholder "{0}" with a user name of the request during runtime. The user service then concatenates theldapUserIdRdnPatternwith theldapUserIdBaseDNto create a DN and searches the directory for a user entry. In this instance, users will be found using the prefixuid=and the suffixou=people,o=hq,dc=myco,dc=com(obtained from theldapUserIdBaseDn).ldapUserIdBaseDnis the base LDAP DN from which user searches begin; our searches will use this as the DN.ldapGroupBaseDnis the base LDAP DN from which group searches begin; searches for groups will use this.
Instead of specifying credentials in plain text, you can encode credentials with an xor
encoding as in the above example, in an effort to keep the honest people honest. Note
that this is not actually encrypted in any way, and can be easily
reversed—the purpose is to not store the password in plain text so that
someone glancing over an administrator's shoulder will find it harder to remember
the password. If a directory server allows anonymous access, you can remove the jndiSecurityPrinciple and jndiSecurityCredentials parameters from the zero.config; this is discussed in more detail below.
LDAP user service-related parameters in the zero.config file
Zero allows you to configure the LDAP user service using the parameters underneath the /config/security/userservice stanza in zero.config (shown below). However, you don't need to set all of the parameters, as some of these have default values, which you can make use of in our environment. We'll look at the key points of the LDAP user service configuration in following sections.
Table 2. LDAP user service properties in zero.config
| Key | Value | Default value | Note |
|---|---|---|---|
| registryType | file or ldap | file | To use LDAP user service, "ldap" must be set. |
| jndiProviderUrl | JNDI provider URL | N/A | Mandatory |
| jndiSecurityAuthentication | The level of authentication used by JNDI | simple | The value is set to javax.naming.
Context.
SECURITY_
AUTHENTICATION |
| jndiSecurityPrincipal | Administrator's principal | N/A | Mandatory in the directory server disallowing anonymous access |
| jndiSecurityCredentials | Administrator's credential (xor supported) | N/A | Mandatory in the directory server disallowing anonymous access |
| jndiInitialContextFactory | Initial context factory name | com.sun.jndi.ldap. LdapCtxFactory | Optional |
| ldapSearchScope | The search scope set to javax.naming.
directory.
SearchControls. 0(SearchControls.
OBJECT_SCOPE), 1(SearchControls.
ONELEVEL_SCOPE), or 2(SearchControls.
SUBTREE_SCOPE) | 2 | Optional |
| ldapSearchTimeLimit | The search time limit in msec set to javax.naming.
directory.
SearchControls | 30000 | Optional |
| ldapUserIdRdnPattern | The pattern of user entries' RDN. A user name is embedded in the place holder "{0}" . | N/A | Mandatory if the search mode is fixed , and also must be commented out if the mode is flex. Combined with ldapUserIsBaseDN to generate the user entries' DN. |
| ldapUserIdSearchFilterPattern | The pattern of the user search filter. A user name is embedded in the place holder "{0}" . | (&(uid={0}) (objectclass=
inetOrgPerson)) | Mandatory if the search mode is flex and you need another pattern different from the default. |
| ldapUserIdBaseDn | The root where LDAP user service starts to search a user entry from | N/A | Mandatory |
| ldapGroupAttributeType | The attribute type of the group name | cn | Optional |
| ldapGroupBaseDn | The base DN of groups | N/A | Mandatory |
| ldapGroupSearchFilterPattern | The filter to search groups which a user belongs to. A user name is embedded in the place holder "{0}". | (&(uniqueMember={0}) (objectclass= groupOfUniqueNames)) | Mandatory if you need another pattern different from the default |
| ignoreBaseDN | Boolean flag support fully qualified domain name (FQDN) lookups. If false, FQDN lookups will be disabled. | true | Mandatory if you want to disable fully qualified distinguished name lookups |
| fullBaseDNFilterPattern | The filter to search for a user based upon the fully qualified domain name | (objectclass=*) | Mandatory if you need another pattern different from the default |
Note: The table above is the complete list of configuration parameters at the time this article was written. For the most up-to-date list of parameters, refer to the section Configuring the LDAP user service in the zero.config file of the Developer's Guide.
Validating the migration to LDAP
Now that we have configured the LDAP repository with the tooling of your choice and modified the configuration as demonstrated above, we are ready to confirm that what we have done functions properly. We'll start by using Wizard, who is an existing user from the previous article. Start the application, make a request to tips.groovy, and start the authentication process again to ensure that the Wizard is able to add and delete the hot stock tips (see Figure 2).
Figure 2. Logged in as the Wizard in group 'wizards'

Close the browser and start the login process again by making a request to tips.groovy—but this time, use Alice (another user from the previous article). Validate that Alice can only see the list of stock tips (see Figure 3).
Figure 3. Logged in as Alice in group 'pundits'

What you have learned about LDAP so far...
At this point, you have already done the hard part of configuring an LDAP repository and porting existing users from the existing file-based user registry. In addition to porting the users over to the new repository, you have configured the application to use the LDAP repository for its user profile and authentication store.
Using LDAP to further group pundits
As the number of pundits has grown, the Wizard would like to further classify these
users into five separate groups associated with pundits, such that he can provide various levels of quality of service depending upon the group the user is a member of. Because this process was done to distinguish between the pundits and the wizards, this should be rather straightforward. Table 3 demonstrates the proposed user and group mapping for the about-to-be restructured LDAP repository. If you are interested in following along with the article, then download and import the LDAP Data Interchange Format (LDIF) file, myco.simple.ldif, to the LDAP directory server.
Table 3. Mapping between users and groups in the simple directory sample

- The following five group names are defined underneath
ou=group,o=hq,dc=myco,dc=com:- sages
- bards
- oracles
- savant
- master
- Each user name belongs to a group.
- "mary" and "dan" belong to "sages".
- "ryan" and "baxter" belong to "bards".
- "bob" and "steve" belong to "oracles".
- "tim" and "john" belong to "savant".
- "ken" and "michael" belong to "master".
Figure 4. Simple directory sample

To take advantage of the newly formed groups, we introduce the concept of roles for securing resources. Because each of these new groups is related to 'pundits', we can continue to use this grouping for securing resources through the use of roles instead of the formerly used method of groups. Roles are used in Project Zero as a way to collect a set of users and or groups under a common name. In the configuration below, we made two small changes. The first change is in the configuration where we previously had a security rule for GET methods to be for users in either the 'pundits' or 'wizards' group. We will now configure the security rules for either the users in the group 'wizards' or in the roles 'pundits'. The role 'pundits' will consist of the groups 'sages', 'bards', 'oracles', 'savant', and 'master'. If we have a need in the future for further subgrouping of users into other groups of type 'pundits', all that is required is to update the role 'pundits' to include this new group in the zero.config, and no code changes are required.
Listing 2. Updated zero.config to leverage new concept roles
/config/http/port=8080
/config/security/realm="Private Hot Stock Tips"
/config/security/roles/pundits/groups=["sages", "bards", "oracles", "savant", "master"]
@include "security/form.config"{
"formLoginPage" : "/login.html"
}
@include "security/rule.config"{
"conditions": "(/request/path =~ tips.groovy(/.*)?) && (/request/method == GET)",
"authType": "Form",
"groups": ["wizards"],
"roles": ["pundits"]
}
@include "security/rule.config"{
"conditions": "(/request/path =~ tips.groovy(/.*)?) && (/request/method == POST)",
"authType": "Form",
"groups": ["wizards"]
}
|
Listing 3 below also has one small change to the groovy code to switch from using groups to roles. The previous article in this series (section entitled "Programmatic authorization") gave an overview of two key attributes of the request subject called 'groups' and 'remoteUser'. A third attribute of the request subject that we have not reviewed is called 'roles', which will contain a list of the roles the user is a member of in the case that the user is a member of a role (similar rules apply for 'groups').
Listing 3. Update stock tips to display different views based on groups and roles
if(request.auth.subject.groups[].contains("wizards")){
request.view = 'wizards.gt';
} else if(request.auth.subject.roles[].contains("pundits")){
request.view = 'pundits.gt';
} else request.view = 'tips.gt';
|
Validating the restructuring of the LDAP repository
Now that the LDAP repository has been configured with the tooling of your choice and the configuration modified as demonstrated above, we are ready to confirm what we have done functions properly. At this point, you should be able to add and remove hot stock tips for the user 'Wizard' and see the list of stocks for any user that is a member of a group listed in the role 'pundits'. In an effort to keep the article condensed, we suggest that you validate that the changes made actually work, to further emphasize how each of these changes impacts the application. The following section, "What you have learned about LDAP so far," will help emphasize these points, and the remaining sections validate the concepts we have just reviewed.
What you have learned about LDAP so far...
At this point, you have restructured the LDAP repository to associate users with more than the default group of 'pundits'. You have also introduced the concept of roles to avoid having to update the application code each time a new group of users wants to be a member of the 'pundits' role.
Figure 2 illustrates the simple directory where users and
groups are located in one subtree, but you don't always have such a simple
directory in a real production system. Now we'll look at a slightly more complicated directory. Figure 5 shows the next sample directory, which can be created by downloading and importing the LDIF file myco.complicated.ldif. Taking the previous simple directory sample as a starting point, we move wizards to a different search group that the LDIF file defines (see also Table 4):
- One user is defined underneath
ou=people,o=branch,o=hq,dc=myco,dc=com.- wizard for a user name and wizard_pwd for a password
- One group is defined underneath
ou=group,o=branch,o=hq,dc=myco,dc=com.- wizards
- "wizard" belongs to "wizards"
If you use the LDAP user service configuration shown in Listing 2, you cannot log in
with 'wizard', although you can log in with the ten users defined in the previous sample. The reason for this is that the template "uid={0}" specified with ldapUserIdRdnPattern and the search root ou=people,o=hq,dc=myco,dc=com specified with ldapUserIdBaseDn does not match the DNs of wizard in the group 'wizards'. So what should you configure for this directory?
Figure 5. Complicated directory sample

Table 4. Mapping between users and groups in the complicated directory sample

To find 'wizard' in the directory search, you should use the user service ldap
stanza in zero.config shown in Listing 4. Note that only the
ldapUserIdBaseDn parameter is needed for the user
search, and ldapUserIdRdnPattern is not needed anymore.
The user service searches the directory with the default search filter of o=hq,dc=myco,dc=com to the leaf and then can find 'wizard' underneath ou=people,o=branch,o=hq,dc=myco,dc=com, as well as ten users underneath ou=people,o=hq,dc=myco,dc=com.
The type of search filter and ldapUserIdBaseDn is called
flex mode, while the search with ldapUserIdRdnPattern and ldapUserIdBaseDn
is called fixed mode. Fixed mode is a basic user search. The definition of ldapUserIdDnPattern is intuitive and simple, where you don't need advanced LDAP skill. Although you can use fixed mode search for a simple directory where all users are defined in one directory branch, it is impossible to use fixed mode to search for a directory where users are defined as distributed in several branches (as depicted in Figure 2). You should use flex mode in this instance. While there is only one mandatory parameter, ldapUserIdBaseDn, which you must configure in zero.config in flex mode, you need to specify a custom search filter for the ldapUserIdSearchFilterPattern parameter when your LDAP directory uses other object classes and other attributes for definition of users and groups different from the default of user service. You'll see the custom search filter in the section "Deep dive in modification of zero.config" later in the article.
Listing 4. zero.config snippet—User service configuration for the complicated directory sample
/config/security/userservice/registryType="ldap"
/config/security/userservice/ldap += {
"jndiProviderUrl":"ldap://localhost:10389/",
"jndiSecurityPrincipal":"uid=admin,ou=system",
"jndiSecurityCredentials":"<xor>LDo8LTor",
"ldapUserIdBaseDn":"o=hq,dc=myco,dc=com",
"ldapGroupBaseDn":"o=hq,dc=myco,dc=com"
}
|
What you have learned about LDAP so far...
At this point, you have restructured the LDAP repository and associated users with more than the default group of 'pundits'. In addition, you have learned the difference between flex mode and fixed mode for LDAP. You have also seen how to configure the Zero configuration to support these modifications, as this is a more commonly seen LDAP repository than the more simplified version you have seen in previous examples.
Anonymous LDAP directory access
An LDAP directory server is sometimes configured to allow anonymous access, where LDAP clients can delegate authentication to an LDAP server without administrator's principal and credentials. The LDAP user service is an implementation of the LDAP client and can anonymously access directory servers.
If a directory server has a directory like that shown in Figure
1 and it allows
anonymous access, you should add user service configuration in Listing 5 to zero.config. It is identical to Listing 4, but without the parameter definitions for jndiSecurityPrincipal and jndiSecurityCredentials. When jndiSecurityPrincipal and jndiSecurityCredentials are not configured, the user service uses anonymous access to the directory server.
Listing 5. zero.config snippet—User service configuration for anonymous directory access
/config/security/userservice/registryType="ldap"
/config/security/userservice/ldap += {
"jndiProviderUrl":"ldap://localhost:10389/",
"ldapUserIdBaseDn":"o=hq,dc=myco,dc=com",
"ldapGroupBaseDn":"o=hq,dc=myco,dc=com"
}
|
What you have learned about LDAP so far...
You have discovered a second popular option for LDAP access called anonymous authentication. Note that while this method of binding is easier to set up, it does not require any authentication to access the LDAP repository.
Deep dive in modification of zero.config
The object class of LDAP is a type of schema defining which attributes an entry should hold in a directory. So far, you have looked at two directories that use default object classes of user service to define entries for users and groups. In a real production system, object classes depend on the requirements and design of an LDAP directory, and you don't necessarily use default object classes of user service. Now we'll look at how to configure user service in a directory where non-default object classes and attributes are used.
Suppose you have a directory like that shown in Figure 3,
built by the LDIF file myco.complicated.mail.ldif
(included in the attached download), where users are mapped
to groups like in Table 5:
- User entries are defined with the default object class
inetOrgPerson. However, user names are stored with themailattribute instead of theuidattribute. - While
uidis the default attribute in user service with which user names are stored,mailis not. - Group entries are defined with the object class
groupOfNames, and member users are defined with thememberattribute. - While
groupOfUniqueNamesis the default object class in user service for group entries,groupOfNamesis not. - While
uniqueMemberis the default attribute in user service with which member users are stored,memberis not.
This directory is tangibly defined with a non-default object class and attributes. To allow the user service to access such a directory with a non-default setting, you need to modify several parameters in zero.config.
With a non-default setting for user entries, you must modify the parameter ldapUserIdSearchFilterPattern. ldapUserIdSearchFilterPattern specifies a search filter to search for a user entry, and its default value is (&(uid={0}) (objectclass=inetOrgPerson)). This is a search filter to search for a user entry whose name is stored with the attribute uid and whose entry is defined with the object class inetOrgPerson. This example has user names with the attribute mail. Therefore, this parameter should be modified to ldapUserIdSearchFilterPattern=(&(mail={0}) (objectclass=inetOrgPerson)), for instance.
In a case where a non-default object class and attributes for group entries are used,
you have to modify the parameter ldapGroupSearchFilterPattern. This parameter is used to define a search filter for group entry search, and its default value is (&(uniqueMember={0}) (objectclass=groupOfUniqueNames)). This filter asks JNDI to search for groups whose member user name is stored with the attribute uniqueMember and whose entry is defined with the object class groupOfUniqueNames. This example has member user names with the attribute member and uses the object class groupOfNames for group entries. Therefore, you should modify this parameter to ldapGroupSearchFilterPattern=(&(member={0}) (objectclass=groupOfNames)), for instance.
Listing 6 shows a sample configuration snippet for search for this directory.
Figure 6. Complicated directory sample with mail attribute as user name and groupOfNames for group's objectClass

Table 5. Mapping between users and groups in the complicated directory sample

Listing 6. zero.config snippet—User service configuration for the directory with mail attribute as user name and groupOfNames for group's objectClass
/config/security/userservice/registryType="ldap"
/config/security/userservice/ldap += {
"jndiProviderUrl":"ldap://localhost:10389/",
"jndiSecurityPrincipal":"uid=admin,ou=system",
"jndiSecurityCredentials":"<xorgt;LDo8LTor",
"ldapUserIdSearchFilterPattern :"(&(mail={0}) (objectclass=inetOrgPerson))"
"ldapUserIdBaseDn":"o=hq,dc=myco,dc=com",
"ldapGroupSearchFilterPattern":"(&(member={0}) (objectclass=groupOfNames))",
"ldapGroupBaseDn":"o=hq,dc=myco,dc=com"
}
|
What you have learned about LDAP so far...
You have discovered how to configure LDAP using an e-mail address versus a user name. Because e-mail addresses are another form of a unique identifier within the enterprise, this is another commonly used and popular configuration.
We hope you have learned about all the steps required to enable the security runtime in Project Zero and how to protect your applications using LDAP. We discussed setting up a user registry and ways to extend a user service registry. Stay tuned for Part 3 of this series, which will expand upon these concepts and help you use Project Zero securely.
| Description | Name | Size | Download method |
|---|---|---|---|
| Sample code for this application | wa-pz-security2.zip | 3KB | HTTP |
Information about download methods
Learn
-
"Enable C++ applications for Web services using XML-RPC"
(developerWorks, June 2006) is a step-by-step guide to exposing C++ methods as
services.
- Get the resources you need to advance your skills in the architecture arena in the
Architecture area of developerWorks.
-
You can learn about LDAP in more detail on the IETF Web site.
- Refer to the Project Zero Developer's Guide for a complete overview of Project Zero security configuration.
- Because this article assumes that you have already
installed the appropriate Project Zero plug-ins from the Eclipse Update site and that you know how to create a Project Zero application within Eclipse, if you haven't already done so and need to do so, refer to the Core Getting Started page of the Developer's Guide before continuing.
- Join the
Project Zero community and see what all the buzz is about!
-
Browse the developerWorks Web development zone to find tools, code, and resources to get you started developing Web 2.0 applications today.
-
The developerWorks Ajax resource
center is packed with information for all skill levels to help you build Ajax into
your applications and dramatically improve your users' Web experience.
Get products and technologies
- Download Apache Directory studio, a useful LDAP tool.
- Download
JXplorer, another useful LDAP tool.
-
Download Project Zero and start applying the skills learned in this article.
- Download
IBM product evaluation versions
and get your hands on application development tools and middleware products from
DB2®, Lotus®, Rational®, Tivoli®, and
WebSphere®.
Discuss

Todd Kaplinger is a Senior Software Engineer in IBM's Software Group currently working as Architect and Team Lead of the Security Team for Project Zero. Todd is an expert in Web-based technologies such as JSP, Servlet, and PHP with a recent focus on emerging Web 2.0 technology and its impact on the enterprise. Todd is currently a member of the expert group responsible for JSR 223: Scripting for the Java™ Platform and is also a member of the Open Ajax Alliance with an interest in interoperability between various Ajax framework implementations regarding security. Todd's previous background was as Team Lead and Architect of WebSphere's Webcontainer and Remote Request Dispatcher (RRD) and participated in the JSR 154 Servlet 2.5 Specification as IBM's representative in the Servlet Expert Group. You can reach Todd at todkap@us.ibm.com.

Hiro Tarusawa is a Certified Consulting IT Specialist in IBM Software Group currently working as the technical consultant for Project Zero and WebSphere products. Before consultant, he had designed and developed security functionality of Project Zero in IBM RTP Laboratory. He has over-ten-years experience of Java technology and is expert in Java EE. He has led many Java EE based system developments in customers' engagements so far.

Simon Kapadia is the Technical Team Lead for IBM Software Services for WebSphere (ISSW) in the United Kingdom. He works on designing and implementing large distributed computer systems for IBM customers. Simon holds a Bachelor’s degree in English and Drama, and a Master’s in Computing Science. He has owned a computer since six years of age, and has turned a lifelong hobby into a career. Prior to joining IBM, Simon developed software for digital exchanges at Bell Laboratories, managed networks and Web applications at a Polish ISP, and supported and consulted on DCE, DFS and Encina for Transarc Corporation. You can reach Simon at simon_kapadia@uk.ibm.com or via his public Web site at http://www.kapadia.pl/.





