【转】Active Directory Information for .NET Programmers

http://www.sqlsoft.com/AboutThisSite/Newsletter/0411/0411_AD4dotNET.html?REF=NOV04NEWS

 

Active Directory Information for .NET Programmers


What Is It?

Network folks have been talking about how great LDAP is for years (Lightweight Directory Access Protocol for all of you that need those acronyms spelled out). We developers have been busy doing other things and have mostly ignored what Active Directory (AD) could do for us. The result is applications that are not very network aware.

As a developer, I have been much more inclined to develop a new HR database for an application then to pull the existing information from Active Directory. Redundant data is bad.

You can also use LDAP to make new friends. You can do most administrative tasks with a little code, helping the network folks out. This comes in really handy when you forwarded that offensive joke to your boss by accident and need them to delete it. You can trade for an application that adds users.

Where Do I Start?

Whenever you connect to AD, you need to start somewhere. I am going to run a program against an OU (Organizational Unit) called WST in a domain called NWTraders.msft. In front of everything, we put LDAP:// (case sensitive) so our program knows what provider to use.

This will look like:

LDAP://OU=WST,DC=NWTraders,DC=msft

Too hard? Just ask the network folks where to start. Of course, you are bound to get a "What are going to do with my network?" response. I recommend slipping them a twenty. If all else fails, start with the very root of the domain (my case "LDAP://DC=SQLSoft,DC=com") for the sqlsoft.com domain.

For all my examples, I have a textbox called "txtAdsPath" where I put the path.

NOTE: The entire code can be downloaded for free if you have an account on My SQLSoft. (Accounts can be created free.) My entire code can be downloaded here:

I also made an active directory browser. I hope that it will help with learning the structure of you domain. You can download my AD browser here:

Just the Facts

Let's get somebody and make them spill a little info. As a general rule (I say "general" for all the Active Directory purists out there), we can see all the information from the AD we are logged into.

First grab an item... any item. I use a textbox called txtAdsPath for the path to our object so that we can try out many of them. I also use a listbox called lstResult to display the results. lstResult.Items.Add just adds a new line to the listbox.

DirectoryEntry is an entry in Active Directory. If we pass in a path when you create a DirectoryEntry, you get that entry. Pretty cool! I display the name ("OU=LuckyUsers" for "LDAP://OU=LuckyUsers,OU=Hawaii, DC=SQLSoft,DC=com"), the GUID (remember that big numbers make you look smart), the ADsPath (matches what you typed in), and finally a count of the properties.

C#

 

VB.NET

All the Facts

Let's go a step further and list all of the properties. The actual list of properties of an object in Active Directory can change. The Active Directory has a schema that defines each object. Those very select few have the right to change that schema.

If you want to have a little fun, go to the network folks and insist that your account needs to be added to the Schema Admins Group. Better yet, say you are working on a Web page and need the ASP.NET account added to Schema Admins. Then run.

Here I list all the properties for an object. Remember that I gave you the browser above.

C#



VB.NET

This code is just like the last example except for a loop through all the properties. We quickly notice that not all properties are meaningful. Many are not being used or for other reasons, not returning a simple value.

All My Children

AD is hierarchal. (Me love big words.) An object, like an OU, may have children (the groups and users in that OU). A fun way to spend the day (OK, just fun for me) is to start with the top level domain and list the children, then the children of the children, and so on.

For my next trick, I will modify the code from above (higher in the article, I mean), to list all the children from an object. This is much more interesting if the object has children (like an OU).

C#

VB.NET

Where Is It?

By now we have a little idea about how to get information out of AD, but sometimes we don't even know where we are. Unless you are the network person who set the whole thing up or you actually read documentation, you probably need to go searching for the objects you care about.

We still grab a DirectoryEntry object, but then we pass it off to a DirectorySearcher object along with a filter. (I use a textbox called txtFilter.)

This time the DirectoryEntry is pointing to our starting point of the search, not the object we are looking for. Maybe we only want to look in a particular OU so we may start in that OU.

The filter is a little hard to explain. We have a couple magic characters.

& And
| Or
! Not
* Wildcard

The use of parentheses is a little odd. We group with parentheses. If I had two things I was looking for, I would group each criterion with parentheses. Then I would put them both in an outer set with a "&" as the first character inside.

You can also use wildcards...

  • Everyone who's firstname, for example, starts with M:

(givenName=M*)

You can add two things together...

  • All users that are people:

(&(objectClass=user)(objectCategory=Person))

You can show off...

  • All users with a telephone... (Sorry to the Amish):

(&(objectClass=user)(telephoneNumber=*))

  • All users without a telephone:

(&(objectClass=user)(!(telephoneNumber=*)))

  • All users in Washington or Oregon:

(&(objectClass=user)(|(st=WA)(st=OR)))

Remember that | (pipe) is that thing looks on the keyboard like a colon except with little lines instead of dots. (Pop quiz later.)

  • Anyone but an Oregonian... (They aren't even allowed to pump their own gas):

(&(objectClass=user)(!(st=OR)))

Okay, enough about the filter. Let's look at actually running the search. The way I have set up the code, I have assumed that I might return more than one thing. Thus I have used the FindAll method instead of the FindOne method, which is for looking for something unique. Also note that the filter is in a textbox called txtFilter.

C#

VB.NET

Are You Somebody?

Sometimes we want to see if someone is valid. I started working on this because someone asked a pretty simple question... "I want to use ASP.NET forms-based authentication, but I want to use the domain username and password for employees and a custom database for anonymous Web users." That is really not a simple question, but here was the toughest part... "Check a username and password against Active Directory first."

Here's how this goes:

1.       Grab a directory entry object, but this time, pass in the username and password.

2.       Set up a filter looking for that person. (The path in Step 1 should be an object that contains the user; make it the root of the domain to be safe.)

3.       Try it and see if it blows up with an exception.

C#

VB.NET

Changing the World

Believe it or not, you can't change, add, or delete things unless you have the rights to do so. If you only care about reading AD and not changing it, you can skip this section. (I won't tell your boss.) Spend the time instead by looking a pretty pictures of airplanes (http://www.airliners.net).

There is a great saying from the sixties... "If you are not part of the solution, you might as well enjoy being part of the problem." (I might be a little off.) Let's be part of the problem and start messing things up in AD. I am, of course, kidding. You need a development environment to work with. Try looking up "Active Directory Application Mode" (ADAM) in Technet. Here is a hyplerlink that will probably change before this arcticle gets published: (http://www.microsoft.com/windowsserver2003/adam/default.mspx).

Adding a New User

I choose the hardest thing here just because it will illustrate all we have to do. If you only want change something that already exists, just grab the object, change the properties, then call commitchanges. Instead, adding a user requires a bit more work.

Here are the basic steps:

1.       Get the object you want to add the new item in (oOU).

2.       Add to the children of the thing you made in Step 1. Note that we have to give the new user a name (like "cn=John.Doe") and also tell AD what type of thing it is ("user").

3.       Set up some properties. Note that the syntax is a little odd. You Add(value) to the Properties(propertyName). If we where changing an existing item, we would just assign the property a new value.

4.       Then we save it. Calling the method Save would have made sense so instead they decided to call it CommitChanges as if we are doing some fancy database thing.

If we where adding an OU or group we would be done. With a user, a little more work is needed. We can only enable a user and set the password after the user is saved back to AD.

5.       Invoke the setPassword method, passing it the password ("P@ssw0rd").

6.       Cast the object to a COM interface just to set the AccountDisabled = false (yuck). They just didn't expose the AccountDisabled method in .NET.
a) Set a reference to the COM AD library.
b) The oNewUser object has a NativeObject Property that gives you access to the COM active directory object(IADsUser) that scripters have been using for years. This object has the AccountDisable property that you set to false. Disabled = false would be enabled. (English teachers don't make computer programs, or least not ones with double negatives.)
Here is what the IADsUser class looks like in the object browser.

7.       Save it again (CommitChanges)

CS Example

VB.NET

Final Notes

What's error handling? Yes I know, these programs desperately need error handling in them. I left it out for one reason... to keep it simple.

I hope I have demystified the System.DirectoryServices a little. My point certainly wasn't to show you everything but enough to get started.

As always, if there is any questions and/or errors, please e-mail me: Mike.Bailey@sqlsoft.com

posted on 2009-07-12 23:36  romanticoder  阅读(1120)  评论(1编辑  收藏  举报

导航