|
|||||||||||||||||||||
|
|||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
IntroductionIn addition to Microsoft SQL Server as a data store, most of the modern infrastructure solutions for enterprises also include Microsoft Active Directory. In many cases, AD can serve as a very useful source of users’ information. To get this information, developers have to query Microsoft Active Directory. For example: get a list of users, get a list of users of the particular group, get a particular user information such as first or last name, and so on. Microsoft .NET Framework provides a standard library for working with Active Directory: Getting StartedTo start querying Active Directory from your C# code, you simply add a reference to the System.DirectoryServices.dll in your project and the following using System.DirectoryServices;
According to examples provided in the Visual Studio.NET Help, Microsoft recommends using two main classes from the User Oriented QueriesUser NameFirst of all, I have to tell that a user-oriented query always uses a user name as a parameter. Let’s figure out what the user name is. This is the name part of a login name, which users enter while logging in Windows. This name part follows the ‘\’ symbol that separates the domain name and the user name. It’s a good practice to extract the user name from the login name before using it in the AD query. We can do it easily: string ExtractUserName(string path)
{
string [] userPath = path.Split(new char [] {'\\'});
return userPath[userPath.Length-1];
}
First QueryNow we know the user name, and it’s good to know if this user exists in the AD. Let’s do it like: bool IsExistInAD(string loginName)
{
string userName = ExtractUserName(loginName);
DirectorySearcher search = new DirectorySearcher();
search.Filter = String.Format("(SAMAccountName={0})", userName);
search.PropertiesToLoad.Add("cn");
SearchResult result = search.FindOne();
if (result == null)
{
return false;
}
else
{
return true;
}
}
This is our first AD query, so let’s see what we are doing here. First of all, I extract the user name from the login name that we received from Windows, using the Actually, the query itself is located in the Now I have to assign a After all, we are ready to run a query. I simply call a lang=csstring cn = (string)result.Properties["cn"][0]; The result object contains a special property named search.PropertiesToLoad.Add("samaccountname");
search.PropertiesToLoad.Add("givenname");
search.PropertiesToLoad.Add("sn");
SearchResult result = search.FindOne();
...
string samaccountname = (string)result.Properties[“samaccountname”][0];
string givenname = (string)result.Properties[“givenname”][0];
string surname = (string)result.Properties[“sn”][0];
The example above contains the names of the most widely used properties. You can for sure retrieve any possible property from AD simply using its name. That’s it actually. Now I am going to show you several more queries, but you already know how to query AD. User’s GroupsLet’s find out what groups our user belongs to. See the code: string GetADUserGroups(string userName) {
DirectorySearcher search = new DirectorySearcher();
search.Filter = String.Format("(cn={0})", userName);
search.PropertiesToLoad.Add("memberOf");
StringBuilder groupsList = new StringBuilder();
SearchResult result = search.FindOne();
if (result != null)
{
int groupCount = result.Properties["memberOf"].Count;
for(int counter = 0; counter < groupCount; counter++)
{
groupsList.Append((string)result.Properties["memberOf"][counter]);
groupsList.Append("|");
}
}
groupsList.Length -= 1; //remove the last '|' symbol
return groupsList.ToString();
}
We can notice that the Common QueriesCommon queries allow us to retrieve much more information from AD. This type of queries are potentially dangerous because of potentially huge amount of information that might be received back from AD. So you have to be careful while experimenting with such queries. Group’s UsersLet’s get a list of users belonging to a particular AD group. The code below shows how to do this: ArrayList GetADGroupUsers(string groupName)
{ SearchResult result;
DirectorySearcher search = new DirectorySearcher();
search.Filter = String.Format("(cn={0})", groupName);
search.PropertiesToLoad.Add("member");
result = search.FindOne();
ArrayList userNames = new ArrayList();
if (result != null)
{
for (int counter = 0; counter <
result.Properties["member"].Count; counter++)
{
string user = (string)result.Properties["member"][counter];
userNames.Add(user);
}
}
return userNames;
}
Here I use the same search filter as for user search, but different set of All UsersThe last query I want to discuss in this article is meant to return a list of all the AD domain users. This is an extremely risky operation because of a large amount of users in the AD domain and possible incorrect implementation of AD. I’d like to explain the second sentence. This query uses a special search filter that looks for every object with a specific property that should mean this object is a user object. But sometimes administrators design AD structure even without this property or enter new records to AD not setting this property. So it’s very possible to get a list of all objects in AD instead of domain user objects only. But it’s enough of bad things, let’s get to the code. ArrayList GetAllADDomainUsers(string domainpath)
{
ArrayList allUsers = new ArrayList();
DirectoryEntry searchRoot = new DirectoryEntry(domainpath);
DirectorySearcher search = new DirectorySearcher(searchRoot);
search.Filter = "(&(objectClass=user)(objectCategory=person))";
search.PropertiesToLoad.Add("samaccountname");
SearchResult result;
SearchResultCollection resultCol = search.FindAll();
if (resultCol != null)
{
for(int counter=0; counter < resultCol.Count; counter++)
{
result = resultCol[counter];
if (result.Properties.Contains("samaccountname"))
{
allUsers.Add((String)result.Properties["samaccountname"][0]);
}
}
}
return allUsers;
}
If we go through the code above, we can see some differences from the previous examples. First, I use a "LDAP://DC=<domain>"
Here DirectoryEntry entryRoot = new DirectoryEntry("LDAP://RootDSE");
string domain = entryRoot.Properties["defaultNamingContext"][0];
DirectoryEntry entryDomain = new DirectoryEntry("LDAP://" + domain);
This is an example of using a Well, let’s get back to the code. The next thing you may want to pay attention is a Best PracticeIn the examples above, I was using a simplified code for demonstration purpose only. But the real code could be much more complex. Especially in the part of
ConclusionThis article is aimed to illustrate the opportunities of working with Microsoft Active Directory provided by the .NET Framework library. Here I have shortly described a common methodology of building AD queries using the .NET Framework standard features. This methodology was illustrated by a number of code examples that can be used practically. Also, some practically proven tips are provided. Using the approach described, developers can create their own AD queries and extend the ones suggested. | ||||||||||||||||||||