This paper provides ten tips for optimizing operation of Site Server 3.0 Commerce Edition Personalization and Membership services:
This paper also provides a list of resources containing additional information on Personalization and Membership services.
Before deploying a Membership Directory implementation, it is important to understand some fundamental concepts behind the Membership Directory and directory services in general. Understanding the role a Directory Service plays on your Web site, the architecture of the Membership Directory, and the possible points of failure are all keys to successful deployment of the Membership Directory.
A directory service is a specialized database used to store object-specific data related to your company (such as printers, users, groups, computers, domains, and the like). The Membership Directory is a specialized database used to store object-specific data related to your Web site.
There are some major differences between a Membership Directory and a generalized database. The Membership Directory is a specialized data store; the information in it should be relatively static. The Membership Directory can increase the performance of query operations where the data is frequently read more times than it is updated. If the information is highly volatile, consider storing your data in a database. Also, you should store only “meta” information about your Web site, for example, user data, content types and attributes.
It is important to note that you are limited in the types of optimizations you can perform on the Membership Directory itself. Most of the optimizations that you perform are on the client. Also, you don’t have the opportunity to reconfigure or re-index data in the Membership Directory.
Membership Directory | Generalized Database |
Specialized data store. | Generic data store. |
Optimized for Read operations. (The expected ratio of writes-to-reads is 1-to-1000, or 1-to-10,000, depending on how large the deployment is.) | Optimized for Read or Write operations, or both. |
Simple transaction model. (There is no resource manager of the Membership Directory and it can’t take part in large, complex transactions.) | Complex transaction model. |
Limited optimizations. (Most of the possibilities for optimization are on the client side, not on the server side.) | Unlimited user optimizations. |
Figure 1 shows the membership authentication architecture. The authentication service is implemented as a security support provider, similar to Secure Sockets Layer (SSL) or Microsoft® Windows NT® LAN Manager (NTLM). The LDAP directory is a protocol layer on top of a Microsoft® SQL Server™ or Microsoft® Access database used to store credentials, permissions, and user properties.
Figure 1: Membership Authentication Architecture
Figure 2 shows an authentication process. When a user is authenticated for a Web site, the incoming HTTP request passes into Internet Information Server (IIS) 4.0. The membership authentication filter screens every request coming into the Web site. If you require that each request be authenticated, the membership authentication filter queries the Membership Directory to see if the user is listed. If the user is listed, the authentication filter enters the Security Support Provider Interface (SSPI), looks at the Windows NT Security Accounts Manager (SAM), and switches the user context of the thread handling the request to the Windows NT impersonation account used by the Membership Directory. (The default impersonation account is MemProxyUser1, subsequent accounts that you create are named MemProxyUser2, MemProxyUser3, and so on.) It also modifies the token created for the user and applies the Windows NT-specific groups that the user belongs to in the Membership Directory.
Note that the application of group permissions is always dynamic. You should never assign any of the MemProxyUser accounts to any specific groups, or set permissions on a resource based on the user account. The MemProxyUser accounts should always exist independently.
Figure 2: An Authentication Process
The next two tips suggest ideas for solving problems with the Personalization and Membership services.
When you encounter a problem with the Membership Directory or in the authentication process, it is important to know each possible point of failure in the architecture. For example, if your code creates a new user in the Membership Directory, you can determine what components are most likely to be at fault based on the context of the operation.
In this context, the code is most likely using Active Directory Service Interfaces (ADSI) to communicate with the Membership Directory via the LDAP protocol, which in turn is communicating with an SQL Server or Microsoft Access database. At this point, you can assume the failure is in one of three places:
Once you have this information, you can use the tools described in Tip 3 to systematically troubleshoot the failure.
There are several tools available to assist you with troubleshooting the Personalization and Membership services:
Troubleshooting Tool | Useful for… | Obtain from… |
Network Monitor (Net Mon) | Tracking HTTP & LDAP traffic. | Microsoft BackOffice® 4.0 & 4.5, and SMS 1.2 & 2.0. |
RegMon & FileMon | Tracking security issues. RegMon tracks the Registry. File Mon tracks the file system. | http://www.sysinternals.com |
Error Lookup | Tracking down phantom errors and translating HRESULTS into a readable error description. | Microsoft Visual Studio® or the Platform SDK |
SQL Trace | Tracking down LDAP failures. | SQL Admin Tools |
This section provides tips for improving the performance and scalability of the Personalization and Membership services.
Certain aspects of the underlying SQL Server database used for the Membership Directory can be tuned and optimized to meet the needs of your Web site. See the Membership Directory Configuration and Tuning Guidelines white paper for suggestions on how to configure and tune the membership directory.
As mentioned in Tip 1, the Membership Directory serves a very specific purpose as a Directory Service for your Web site. The Membership Directory should not be used as a generalized database. It has been optimized for read operations and for specific types of queries. The rule of thumb for a Directory Service is to write once for every one to ten thousand reads. Although the Membership Directory runs on SQL Server, it should not be treated as an online transaction processing (OLTP) database.
One type of optimization you can control is the method you use to query the Membership Directory. You can optimize your queries by:
The following table explains the scope of various types of queries.
Type of query | Scope |
Base | One SQL query queries the attributes of the object to which you are bound. For example, if you bind to the administrator objects, you can specify “base” as the scope of the query to query only the attributes of the administrator objects. |
OneLevel | Multiple queries to a single namespace (ou=Members,o=Microsoft). (Queries the immediate children of a given object.) |
Subtree | Queries until there are no more child containers. |
To query the attributes of a specific object, specify Base as the scope of the query. Queries with OneLevel scope only query the immediate children of a given object. This is especially useful if you’ve partitioned your database and want to limit your query to a single namespace. The Subtree query scope has the widest possible scope, so use it only in cases where you really need to look at all the children of an object in all possible database partitions.
Querying on indexed attributes yields the highest degree of optimization. Querying on custom attributes requires a table scan and so should be avoided if at all possible.
The following attributes are indexed in the Membership Directory:
Refer to the Membership Directory Configuration and Tuning Guidelines white paper for more information on how to optimize queries against the Membership Directory.
When you bind to an object with ADSI, it caches the LDAP handle for the lifetime of the object, so that when you want to work with the object, you don’t have to rebind it again and again.
Use IADsContainer::GetObject() to bind to a container, as shown in the following code example:
IADsContainer::GetObject()
Dim adsConn
Dim adsChild
Dim strBindDn
strBindDn = “LDAP://server:port/o=realm/ou=Members”
‘Perform the authenticated bind
Set adsConn = GetObject(“LDAP:”)
Set adsConn = adsConn.OpenDSObject(strBindDn, “cn=Administrator,ou=Members,o=Microsoft”, “password”, 0)
‘Use the existing connection to bind to a single object
Set adsChild = adsConn.GetObject(“member”, “cn=JaneDoe”)
‘Work with cn=JaneDoe
‘…
Set adsChild = Nothing
‘Bind to a new object
Set adsChild = adsConn.GetObject(“member”, “cn=JohnDoe”)
‘…
The next tip describes how to maximize security for your Membership Directory.
The default Windows NT impersonation account used by the Membership Directory is MemProxyUser1. This is the account that logs on to Windows NT for each user that is logged on to a Membership authenticated Web site. Since only one account is used for every user that logs on, security is handled entirely through the Windows NT groups that you create for each group in the ou=Groups container of the Membership Directory.
When applying Access Control Lists (ACLs) to resources on your Web site, it is important that you never assign permissions specifically to the MemProxyUser accounts (MemProxyUser1, MemProxyUser2, and so on). You also need to be cautious when changing the account used for impersonation for the same reason. For example, if you change the account to use “MYDOMAIN\JohnSmith” as the impersonation account, and if you have set ACLs specific to this user, then they will supercede ACLs set for the Windows NT-mapped groups. Then all users on your Web site will have access to the resource.
Another important point to remember is how the impersonation account used by the Membership Directory is logged on to Windows NT. When an authentication request comes in and the username and password supplied are correct, the Membership Authentication Filter calls the LogonUser() Win32 API with the username and password of the impersonation account and sets LOGON32_LOGON_NETWORK to the logon type. This means you cannot access authenticated remote resources and authenticated inter-process communication mechanisms such as named pipes and mail slots, and you will be limited in the use of DCOM components.
For more information on known limitations of how the Membership Directory uses the Windows NT impersonation account, please see Microsoft Knowledge Base article Q214804.
This section contains a tip for working with cookies.
The Membership.VerifUser component is used to issue or re-issue cookies to a user of a Membership authenticated Web site. The following table outlines the appropriate use of each cookie issuing method.
Function | Use when… |
IssueCookieToOldUser() | Moving or renaming objects |
IssueCookiesToNewUser() | Creating a new account |
IssueOldCookiesToNewUser() | Reissuing cookies |
IssueRecentChangesCookie() | Updating user attributes |
IssueCookie() and CancelCookie() | Wrapper for “Set-cookie:” HTTP header |
This section explains how to use the Dynamic Directory.
Dynamic Directory is the term used to refer to the collection of dynamic data managed by the LDAP Service for the Membership Directory.
Dynamic data is available only during the connection between the application server and the client. Each entry is created with an associated time-to-live (TTL), which is decremented until it reaches zero, at which point the entry is deleted.
The purpose of this arrangement is to prevent stale data from accumulating due to client software that may not clean up properly when a connection is broken.
The LDAP Service manages dynamic data. If multiple LDAP Services are configured to support dynamic data, they can replicate the dynamic data so that a complete set of current information is available at each LDAP Service.
P&M dynamic data support is the successor to Microsoft® Internet Locator Service (ILS) in Microsoft Site Server version 2.0.
Dynamic objects are “sub-classed” LDAP objects (derived from objectClass and dynamicObject). LDAP has the concept of a sub-class object that inherits or derives its attributes from two or more objects, similar to multiple inheritance in C++. However, an LDAP dynamic object is derived from whatever object you want to define as a dynamic object and the definition of the dynamicObject class in the Membership Directory schema.
The Dynamic Directory is intended to be an operation that occurs entirely in memory. You must set the containsDynamicOnly attribute to one (1) when creating the container. For more information, see Microsoft Knowledge Base article Q194720. You must also be sure that the computer on which you run LDAP has enough memory to handle a high volume of users on your Web site in order to prevent paging out memory to and from the swap file.
The EntryTTL attribute sets the lifetime of an object. For example, if you set the EntryTTL attribute of an object to 60 seconds, the object is deleted after that time. However, if the setting you pick is lower than the value specified in the Dynamic Directory configuration of the LDAP service, EntryTTL defaults to the higher of the two values. So, if the value specified in the Dynamic Directory is 600 seconds (10 minutes), the object will exist for the full 10 minutes even if you set the EntryTTL attribute for the object to only 60 seconds.
There are a couple of general rules to understand when working with the Dynamic Directory:
The following code examples show how to create dynamic objects with AUO and with ADSI.
Create Dynamic Objects with AUO
Dim auoUser
Set auoUser = Server.CreateObject(“Membership.UserObjects”)
If (Not IsArray(auoUser(“dynamic”).objectClass)) Then
‘Subclass the newly created LDAP object
auoUser.objectClass = Array(“member”, “dynamicObject”)
auoUser.entryTTL = 600 ‘10 minutes
auoUser.SetInfo()
End If
Create Dynamic Objects with ADSI
Dim adsRoot
Dim adsUser
‘Anonymous binding used for brevity
Set adsRoot = GetObject(“LDAP://server:port/o=Microsoft/ou=Dynamic”)
‘Create the new object
Set adsUser = adsRoot.Create(“member”, “cn=JohnDoe”)
‘Set all mustContain props before subclassing
adsUser.Put “GUID”, “1234”
adsUser.SetInfo
‘Now do the subclassing
If (Not IsArray(adsUser.objectClass)) Then
adsUser.objectClass = Array(“member”, “dynamicObject”)
adsUser.entryTTL = 600
adsUser.SetInfo
End If
More information on using the Dynamic Directory can be found in Using the Membership Directory and Active User Object (AUO) for Session State Data.
The following resources provide more information on Site Server 3.0 Commerce Edition Personalization and Membership services.
Type of Resource | Description | Link |
Documentation | Site Server SDK
Site Server Resource Kit |
http://www.microsoft.com/siteserver/commerce/DeployAdmin/SDK.htm |
Web | Product home page
Peer support Introductory peer support ADSI error codes |
http://www.microsoft.com/siteserver/
http://msdn.microsoft.com/library/psdk/adsi/ds2_error_0t9v.htm |
Books | Professional Site Server Personalization and Membership by Robert Howard, ISBN: 1861001940 | Please contact your local bookstore |
Information in this document, including URL and other Internet web site references, is subject to change without notice. The entire risk of the use or the results of the use of this resource kit remains with the user. This resource kit is not supported and is provided as is without warranty of any kind, either express or implied. The example companies, organizations, products, people and events depicted herein are fictitious. No association with any real company, organization, product, person or event is intended or should be inferred. Complying with all applicable copyright laws is the responsibility of the user. Without limiting the rights under copyright, no part of this document may be reproduced, stored in or introduced into a retrieval system, or transmitted in any form or by any means (electronic, mechanical, photocopying, recording, or otherwise), or for any purpose, without the express written permission of Microsoft Corporation.
Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual property rights covering subject matter in this document. Except as expressly provided in any written license agreement from Microsoft, the furnishing of this document does not give you any license to these patents, trademarks, copyrights, or other intellectual property.
© 1999-2000 Microsoft Corporation. All rights reserved.
Microsoft, Windows, Windows NT, BackOffice, and Visual Studio are either registered trademarks or trademarks of Microsoft Corporation in the U.S.A. and/or other countries/regions.
The names of actual companies and products mentioned herein may be the trademarks of their respective owners.