Search Options

The Phone sample demonstrates how to perform a basic search of Active Directory. Programmers can customize searching for various situations, and I'll describe some of those in this section.

Referrals

The Phone sample used the GC provider to search the global catalog. Since the global catalog contains a copy of every object in a forest of domain trees, you can be certain your search is thorough. The limitation of the global catalog is that it contains only a partial set of the attributes of each object. Sometimes it's necessary to search the entire forest for attributes not included in the global catalog, and in that case the global catalog won't be sufficient.

Since Active Directory is a distributed directory, it doesn't store information in just one place and it doesn't maintain copies of the entire directory on each domain controller. Rather, each domain controller contains the directory partition for the particular domain it hosts. Does this mean that clients are expected to query all the domain controllers in a forest, resubmitting the query to each one, looking for matches?

In a word, yes, but don't panic. The process of hunting down the information at the various domain controllers is handled transparently for the application. ADSI, or more specifically, the LDAP API library on the client machine, does the hard work of submitting the query to all relevant domain controllers. This mechanism is known as referral chasing.

Here's an example. Let's say you want to search all the person objects in the directory, looking for anyone who's employee ID is under a certain value. This information is stored in contact and user class objects under the employeeID attribute. Since employeeID is not part of the attribute set stored in the global catalog, you can't use the global catalog and must search the directory partitions of all the domains. In the Copper Software empire, employees are distributed to several domains around the world, such as

coppersoftware.com

clearwater.coppersoftware.com

dublin.coppersoftware.com

To search all the domains, you have to start at the top of the domain tree. The top can be retrieved from the rootDomainNamingContext from the RootDSE object, just as in the VBScript Phone sample. In this case, that would be DC=coppersoftware,DC=com. To make sure all of coppersoftware.com and its child domains are searched, you have to specify the subtree search scope in the query statement. Here is what the LDAP query statement would look like:

 <LDAP://DC=coppersoftware,DC=com>;
(&(objectCategory=person)(employeeID<=9999));
name,employeeID,ADsPath;
subtree

This statement searches all the directory partitions looking for any person class objects that have an employeeID attribute with a value of less than 10,000. The name and employeeID attributes and the ADsPath property of the matching objects will be returned.

When this query is executed, the server responding on behalf of coppersoftware.com will go through all its containers looking for matching objects. As it does so, it builds a result set in memory with the requested attributes. Once all the objects in the current domain directory partition have been searched, the server will automatically add referrals to the result set. A referral is simply a way for the server to indicate that there might be another domain controller that contains the information you're looking for. In the example, a referral will be generated for the clearwater.coppersoftware.com and dublin.coppersoftware.com domains.

How does the server know about other servers? In the case of clearwater.coppersoftware.com and dublin.coppersoftware.com, they are child domains, also known as subordinate domains. The parent domain in a tree keeps information about the tree in its configuration partition and provides distinguished names to child domains in the referral.

After the referrals are added to the result set, the result set is passed back to the program performing the search. At a very low level, the LDAP API library (Wldap32.dll) processes the referral by effectively repeating the search again on the domain controllers for the referrals. Any matching objects from the other domain controllers are added to the result set and returned to the client.

A server can generate referrals to other domain trees, even to LDAP servers on the Internet. The only requirement is that the server has a DNS name. However, unlike referrals to child domains, referrals to external domains can occur only if explicit cross-references to the domains exist in the directory. These references are established by adding a crossRef class object to the configuration partition of the directory. Describing external cross-references in detail is beyond this introduction to referrals, however. Most of the time, you'll be searching within a tree and won't need to be concerned with external cross-references.

As you can imagine, the process of connecting and querying the other domain controllers can be time-consuming. Active Directory will always generate referrals for a client when needed, but referral chasing by a client is turned off by default. Referral chasing is controlled using the Chase Referrals property of the ADSI OLE DB provider. This property is set using the ADO Properties object in the same fashion as the Page Size property. Using IDirectorySearch, the referral chasing option is set by building an ADS_SEARCHPREF_INFO structure containing the ADS_SEARCHPREF_CHASE_REFERRALS constant and one of the values listed in Table 5-4.

Chase Referral Option Description

ADS_CHASE_REFERRALS_NEVER

The client will not chase any referrals generated by the server.

ADS_CHASE_REFERRALS_SUBORDINATE

The client will chase referrals to any child domain within the tree. This flag is ignored during paged searches.

ADS_CHASE_REFERRALS_EXTERNAL

The client will chase only referrals to external domains. This flag is on by default during any ADSI binding operation. This is the default for searching.

ADS_CHASE_REFERRALS_ALWAYS

The client will chase all referrals.

Table 5-4 Options for referral chasing contained in the ADS_CHASE_REFERRALS_ENUM enumeration.

In the next release of Windows, you can set up Active Directory so that it doesn't automatically generate referrals, which will improve performance. A future version of ADSI will use this option if the client won't be chasing referrals. For more information, see Chapter 11.

Asynchronous Searches

Both the VBScript and C++ version of the Phone sample perform a synchronous search. In other words, the client waits for results from the server before doing anything else. Since waiting for the server to search and return a result set can be very time-consuming, you don't want to force your users to be waiting during this time. Setting the Page Size property helps, since it reduces the result set, but even waiting for 20 results can take a while if there are a large number of objects to be searched that don't match the search filter.

With an asynchronous search, control is returned to the program as soon as the first result is ready. The program can display the results of the search to the user and check to see whether EOF was set, indicating that no more results are available. To specify an asynchronous search, you set the Asynchronous property, which is by default False, to True.

For a demonstration, you can modify the VBScript Phone sample with the following line and ask it to return all objects. You'll notice that results are displayed almost immediately, and performance will seem to have increased. Place this line right after the line in which you set the Page Size parameter:

 objADOCommand.Properties("Asynchronous") = True 

Authentication and Security

In Chapter 4, I discussed how to bind to an object using an alternative set of credentials. When performing searches of the directory, ADSI and the ADSI OLE DB provider use the security context of the program being run. As with the ADsOpenObject function, you can specify a different set of credentials to use. You can also set the level of security to use when connecting to and searching the directory.

The ADSI OLE DB provider exposes several properties that control the authentication options. These are listed in Table 5-5.

Property Description

User ID

The name of the account to be used. The format you use is the same as for ADsOpenObject or the OpenDSObject method of the IADsOpenDSObject interface. See the section "Authentication" in Chapter 4.

Password

The password to match with User ID.

Encrypt Password

A Boolean value that specifies whether the password is encrypted. The default is False.

ADSI Flag

Sets the authentication options. Use one or more of the flags from the ADS_AUTHENTICATION_ENUM enumeration. The default is 0.

Table 5-5  ADSI OLE DB provider authentication properties.

You can set these properties in a couple of ways. The first is simply by referencing them in the Properties collection of the ADO Connection object. Here is an example:

 objADOConnection.Properties("User ID") = "COPPERSOFTWARE\Administrator"
objADOConnection.Properties("Password") = "mypassword"
objADOConnection.Properties("Encrypt Password") = True
objADOConnection.Properties("ADSI Flag") = ADS_SECURE_AUTHENICATION

The second way is to use the Open method of the Connection object as the connection string. This method is handy when you're using data access tools that require a connection string instead of coding. The connection string uses the same property names and separates each part with a semi-colon, just like the query statement. However, only the User ID and Password properties can be set this way. For example,

 Provider=ADsDSOObject;User ID=COPPERSOFTWARE\Administrator;
Password=mypassword;

You can see that the provider name is the first property listed in the string. For the ADSI OLE DB provider, this will always be ADsDSOObject. To set the provider programmatically, use the Provider property of the Connection object, as follows:

 objADOConnection.Provider = "ADsDSOObject" 

For more information about credentials and connection options, refer to the section "Authentication" in Chapter 4.

Search Limits

In addition to the Page Size property, the ADSI OLE DB provider has other options you can include to make your applications more responsive when performing extensive searches. These are listed in Table 5-6.

ADO Property and IDirectorySearch Search Preference Description

Page Size ADS_SEARCHPREF_PAGESIZE

Specifies the page size in a paged search.

Size Limit ADS_SEARCHPREF_SIZE_LIMIT

Specifies the maximum number ofreturned objects. If the size limit is reached, Active Directory stops searching.

Server Time Limit ADS_SEARCHPREF_TIME_LIMIT

Specifies the time limit (in seconds) for the search that the server should observe in a search.

Timeout ADS_SEARCHPREF_TIMEOUT

Specifies the time limit (in seconds) that a client is willing to wait for the server to return the result.

Time Limit ADS_SEARCHPREF_PAGED_TIME_LIMIT

Specifies the time limit (in seconds) that the server should observe to search a page of results (as opposed to the time limit for the entire search). If the limit is reached, searching stops and any results are returned. Specifying this option is also supposed to return a "cookie" that indicates the search state so that you can presumably continue searching if desired—I did not explore or test this option.

Table 5-6 Search limit options.

Performance

You should consider a number of pitfalls when creating queries against Active Directory. These have to do with scope and size: by keeping the scope of the search as narrow as possible and asking for as little information as necessary, Active Directory can search and return results more quickly. Here's a list of dos and don'ts:

  • Do search using indexed attributes. These attributes are kept in sorted tables within Active Directory and provide very fast response.
  • Do use paging to improve response to the user and to give the directory server a break.
  • Do use the objectCategory attribute. When looking for particular types of objects, use objectCategory instead of objectClass. The objectCategory attribute is a single-valued attribute containing the most appropriate class name for the object. Both user and contact object classes inherit from the organizationalPerson class, which itself inherits from the person class. The objectCategory attribute contains the value person for all the user and contact objects. This attribute is also indexed for even better performance.
  • Do sort on indexed attributes. If you need the server to sort the result set for you, using indexed attributes helps tremendously since the server can sort as it collects the results. Otherwise, the server must wait until all the results have been collected to sort them.
  • Don't use multivalued attributes in your searches. Attributes containing more than one value are more difficult to search. Multivalued attributes are discussed in the next chapter.
  • Don't use the objectClass attribute when objectCategory will work. The objectClass attribute is multivalued, thus using it reduces searching performance. But here's an exception: Querying on (objectClass=*) is a great way to search all objects. This type of filter is optimized within Active Directory.
  • Don't use substring searches if possible. For example (sn=*mann) or (cn=*soft*).
  • Don't perform subtree searches against the root domain unless required. Doing this will generate referrals regardless of whether you plan on processing them.
  • Don't ask for sorting, particularly multi-attribute sorting unless absolutely required. This requires the server to collect the result set in memory.


MicrosoftR WindowsR 2000 Active DirectoryT Programming
MicrosoftR WindowsR 2000 Active DirectoryT Programming
ISBN: N/A
EAN: N/A
Year: 2001
Pages: 108

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net