Most Read This Week
Connecting CF to LDAP
Connecting CF to LDAP
By: David Anderson
May. 6, 1999 12:00 AM
When I started using ColdFusion, one of the tags that piqued my curiosity most was <CFLDAP>. At the time, I had only a vague idea what LDAP was and when I started to write applications that extended beyond single pages, I realized I needed some kind of authentication. I tried the <CF_LOGIN> tag but wasn't thrilled with the idea of storing usernames and passwords in a table.
At the same time, I was setting up Netscape's Messaging Server. While it can use a local file for user information, it prefers an LDAP directory. I immediately saw the advantage of using the LDAP server for both Messaging Server and my ColdFusion applications. So I set about putting up Netscape's Directory Server.
I quickly learned that LDAP directories are significantly different from SQL databases. An LDAP directory is a specialized database for storing information about people and places. As such, the field names, called attributes, are predefined. Although the actual database structure is fairly flat, the directory itself is treelike. The tree metaphor is used frequently in the LDAP world: branches are where the tree splits, leaves are the terminal entries off a branch.
Populating my LDAP directory proved to be a trial by fire as I learned how to use the <CFLDAP> tag. I used ColdFusion to populate the directory and to maintain synchronization between it and the Oracle database it's based on.
LDAP directories use a fixed list of column names called attributes, which are defined in the LDAP specification. In addition to the attributes listed in the Advanced ColdFusion Development book, you can find a more complete list at www3.innosoft.com/ldapworld/rfc1617.txt.
Like <CFQUERY>, <CFLDAP> handles all interactions with the LDAP directory. You'll use it for querying, inserting, updating and deleting information from the directory. ColdFusion does some error-checking, but more advanced functions are simply passed directly to the directory server. You'll have to rely on the directory server logs for detailed information about bad LDAP operations.
Custom CF LDAP Tags
LDIFToQuery will convert LDAP Directory Interchange Format files into queries. LDIF is generally used for bulk loading and unloading a directory server.
Querying an LDAP Directory
<cfldap name="orglist" server="ldap.itd.umich.edu" attributes="dn" start="c=US"> <cfoutput query="orglist"> #dn#
The equivalent search in SQL would be:
Filters, the rough equivalent of SQL's WHERE, can be used to narrow the query. The syntax for filters is a bit tortured. To select, for instance, just the State University of New York entries in the example above, you'd add this:
filter="(o=State University of New York*)"
Implementing more complex filters is an interesting challenge. For instance, if I want all the people whose last names fall between A and D, I'd use a filter like:
In this example, the | ORs the four subfilters, so it'll return everything from A to D. You can combine filters from different attributes and nest them as much as you'd like. The more complex your filter is, the longer it'll take the LDAP server to process. Filter performance is affected by attribute indexing. If you plan to search frequently on a particular attribute, make sure the directory server indexes it.
SCOPEing the Query
SCOPE can have one of three values: onelevel, base and subtree. The default, onelevel, will go down the directory exactly one branch. That's why we get the organization entries. Base will return entries only at the base level, which is the same as the start.
Subtree, the most productive of all three, will traverse down all branches under the START option, looking for entries that match your filter. If you're not sure where an entry might be, subtree is the easiest way to find it. Since subtree searches the entire LDAP directory, it can take a little longer.
Other LDAP Peculiarities
<cfif len(postaladdress) gt 0>
The standard for postal addresses specifies a maximum of 30 characters in six rows.
Other problems to watch out for are timeouts, maximum number of records and access controls lists (ACLs). The default timeout for queries through ColdFusion is 60 seconds. You can specify a longer timeout; however, you may run into the timeout of the server. There's no maximum number of records ColdFusion will ask for. You can specify a MAXROWS amount if you think your query may return an inordinately large result set. Most servers have an internal limit on the maximum number of entries they'll return. You may want to check the server settings.
Access control lists are a way of limiting who can access what information. For instance, the default ACLs in Netscape's Directory Server prevent a user from changing someone else's password and anonymous users from making any changes. You can implement ACLs that prevent certain fields from being returned or return only those fields to specific users. If you know the field exists and the data's there, chances are an ACL is preventing you from seeing it.
ColdFusion queries your LDAP server as an anonymous user. You can, and probably should, set up a user account in the LDAP directory that your CF server can use. You can give that account permission beyond that of an anonymous user but less than the directory administrator. You'll need to include the USERNAME and PASSWORD options in your <CFLDAP> queries.
Going Beyond Simple Queries
Actually, adding the record is relatively straightforward. You'll need to come up with a distinguished name that matches the one used in your directory server. Next, build the list of required object classes and the attributes list. To actually add the entry, you'll need a username that has sufficient permissions.
In Listing 1, I'm adding Rick Deckard to the Los Angeles Police Department directory. There's no real minimum to the information you must add other than the dn. Your directory server may do syntax checking to make sure you don't add attributes without the appropriate object classes, so it's always a good idea to make sure everything's okay before adding an entry.
In composing the attribute list to add an entry, the object classes come first, followed by a semicolon, then the attributes and their values. Each attribute is separated by a semicolon as well. I build the object class list and the attribute list separately because I sometimes need to add object classes based on the type of user. For instance, if one of my users has an e-mail account, I can easily add the appropriate object classes and attributes.
Modifying Existing Records
Rather than trying to figure out what the dn of an entry should be, I do a query for the record I want to modify. I'll use the dn later in the modify query. The additional hit against the directory server doesn't slow down the process significantly.
In the program I use to keep my directory server in sync with our Oracle database, I'll query the Oracle database and do a lookup and modify for each entry. Even with an update of over 6,000 records, my program will usually run in just a few minutes.
Changing the DN
When changing the dn, you can generally change only the leftmost portion. For instance, the dn for me is:
uid=andersdl, ou=people, o=plattsburgh.edu
Using the modifydn query, only the uid=andersdl portion can be changed. It's not possible to move entries around in the tree structure using modifydn. Instead, you'll have to delete the entry and re-create it under the new branch.
Also, you can't use modifydn to change the name of a branch. If you want to change the ou=people branch to ou=employees, you have to remove all the entries under people, then rename it.
Deleting Attributes from an Entry
If you've heavily modified an LDAP entry and are concerned that it may contain many unused attributes, simply delete the entire record and re-add it.
Deleting an Entry
The delete operation removes only one entry at a time and will not remove leaf entries. If you need to remove a range of entries, you'll have to loop over the list and do a delete query for each. To delete a branch that has leaf entries, remove all its leaf entries first.
Tying It Together
As I mentioned above, directory queries can be sorted on only one field. If you need to sort on last and first name, you'll need to write some code to postprocess the query.
In some of my applications I use groups on the server to grant access to applications. In certain applications I'll generate a select list from the group. Since group queries come back from the server as comma-delimited lists, they require some conversion before they can be used for further queries. In my application I'll get the list of unique members, then build a filter that'll return the users I want. The code below will take a list of uids and convert it to a filter:
<cfset uidq = "(|">
One minor frustration is the inability to select attributes using AS, such as you can do in SQL. If you need the equivalent, you can certainly use the query functions (QueryNew, QueryAddRow, QuerySetCell) to reformat the directory. I've found it convenient when working with data from the directory server that's similar to a query from my Oracle server.
Using LDAP for Authentication
I've configured my ColdFusion server to use the directory server for authentication. If you've skimmed the manual, you've probably noticed it can get complicated. Essentially, you can use your directory server as the source for user authentication. I won't go into how to set up security. Ben Forta's book, Advanced ColdFusion Application Development, covers setting up security rather well.
The only difficulty I've run into has been in adding and removing users and groups via the user administration screens in the CF Administrator. This is a known bug in the current version of ColdFusion Server. I have to type in the dn for users and groups that I want added. Unfortunately, removing users means I have to re-create my user lists.
If you're just starting out with directory servers, try to set up a small test machine. A couple of free LDAP servers run on Linux, so if you have an extra machine, you might want to set it up as your testbed. (By the way, you may have noticed Barbara [Babs] Jansen used in many LDAP examples. If you don't know who she is, search the Internet Movie Database [www.imdb.com] for Martha Smith.)
Reader Feedback: Page 1 of 1
Subscribe to the World's Most Powerful Newsletters