使用 System.DirectoryServices.AccountManagement
在本文中,我们将重点介绍如何使用 .NET Framework 3.5 中包含的 System.DirectoryServices.AccountManagement 命名空间来创建、编辑和删除 Active Directory 或 Machine SAM 上的用户帐户或组。
引言
在本文中,我们将重点介绍如何使用 .NET Framework 3.5 中包含的 System.DirectoryServices.AccountManagement
命名空间来创建、编辑和删除 Active Directory 或 Machine SAM 上的用户帐户或组。我们能够通过使用 .NET Framework 2.0 中 DirectorySearcher
组件返回的 DirectoryEntry
对象的 Invoke
方法来开发这些功能,但这个新命名空间运行速度更快,并且易于开发。它也更面向对象。
在开始之前,让我们先快速浏览一下本文中将要使用的对象。
PrincipalContext |
PrincipalContext 对象提供了目录服务,例如 AD 或 Machine SAM。换句话说,它持有到目录的连接。 |
Principal |
Principal 是我们将要描述的 principal 对象的基类。它包含通用方法,例如 Save 、Delete 。 |
GroupPrincipal |
顾名思义,GroupPrincipal 对象在目录级别上为 Group 对象提供功能,并且派生自 Principal 对象。 |
AuthenticablePricipal |
此类也派生自 Principal 类,除此之外,它还包含用于身份验证机制的方法。 |
UserPricipal |
UserPrincipal 对象代表 Active Directory 或本地 SAM 上的用户,它为用户项提供功能。 |
使用代码
我相信在编程中学习的最佳方法是编写代码。因此,让我们开始编写代码。我将提供一些关键点的示例,并尝试解释使用这些类的工作原理,而不是将所有代码粘贴在这里。
有关更多信息,您可以从上面的链接下载源代码。以下是该程序包含的一些功能。
- 组:列出、筛选、创建、编辑、删除、查看组成员。
- 用户:列出、筛选、创建、编辑、删除、更改密码、查看用户所属组、将用户添加到组、从组中移除用户。
让我们从创建一个 PrincipalContext
对象实例开始。
PrincipalContext insPrincipalContext =
new PrincipalContext(ContextType.Machine);//Connecting to local computer.
PrincipalContext insPrincipalContext = new PrincipalContext(ContextType.Domain, "MyDomain",
"DC=MyDomain,DC=com");
//Connecting to Active Directory
PrincipalContext insPrincipalContext = new PrincipalContext(ContextType.Machine,"TAMERO",
"administrator","password");
//Connecting to local computer
//with credentials of an user
如您所见,连接到 Machine SAM 和 Active Directory 之间没有区别。我将继续在我的文章中提供 Machine SAM 的示例,但正如我所说,没有区别。此外,使用此对象,您可以验证用户的凭据。我将在本文的最后提供一个使用此方法的示例。
现在,让我们看看如何列出或筛选用户或组。
private void SearchGroups(GroupPrincipal parGroupPrincipal)
{
lbGroups.Items.Clear();
PrincipalSearcher insPrincipalSearcher = new PrincipalSearcher();
insPrincipalSearcher.QueryFilter = parGroupPrincipal;
PrincipalSearchResult<principal> results = insPrincipalSearcher.FindAll();
foreach (Principal p in results)
{
lbGroups.Items.Add(p);
}
}
private void SearchUsers(UserPrincipal parUserPrincipal)
{
lbUsers.Items.Clear();
PrincipalSearcher insPrincipalSearcher = new PrincipalSearcher();
insPrincipalSearcher.QueryFilter = parUserPrincipal;
PrincipalSearchResult<principal> results = insPrincipalSearcher.FindAll();
foreach (Principal p in results)
{
lbUsers.Items.Add(p);
}
}
private void ListGroups()
{
GroupPrincipal insGroupPrincipal = new GroupPrincipal(insPrincipalContext);
insGroupPrincipal.Name = "*";
SearchGroups(insGroupPrincipal);
}
private void ListUsers()
{
UserPrincipal insUserPrincipal = new UserPrincipal(insPrincipalContext);
insUserPrincipal.Name = "*";
SearchUsers(insUserPrincipal);
}
现在,让我们看看列出和筛选用户或组的逻辑。您可以轻松地看到 SearchGroups
和 SearchUsers
方法是相似的。最重要的一点是,对于组功能使用 GroupPrincipal
,对于用户功能使用 UserPrincipal
。并且,principal searcher 是提供搜索功能 的公共类。在将包含筛选器的对象(GroupPrincipal
或 UserPrincipal
)分配给该对象的 QueryFilter
属性之后,FindAll
方法返回所有记录,FindOne
方法返回第一条记录。另外一点是关于如何设置搜索条件,例如,对于包含“b”字符的属性,您可以将“*b*”分配给该属性,或者对于以“b”字符开头的属性,您可以将“b*”分配给该属性。我将在本文的最后告诉您如何设置基于比较的筛选器(例如,PasswordExpirationDate
在接下来的 5 天内)。
现在,让我们看看创建新用户的代码。
UserPrincipal insUserPrincipal = new UserPrincipal(insPrincipalContext);
//method that assign properties to insUserPrincipal object
insUserPrincipal.Save();
insUserPrincipal.Dispose();
MessageBox.Show("User created.");
GroupPrincipal insGroupPrincipal = new GroupPrincipal(insPrincipalContext);
//method that assign properties to insGroupPrincipal object
insGroupPrincipal.Save();
insGroupPrincipal.Dispose();
MessageBox.Show("Group created.");
创建条目非常容易。如您所见,在创建 principal 对象(用户或组)后,调用其 Save
方法即可保存记录。编辑和删除的工作方式相同。不是创建一个 Principal
对象,而是获取一个 Principal
对象引用,然后更改属性并调用 Save
方法,您的对象就会更新。要删除条目,您需要做的就是调用引用该条目的 Principal
对象的 Delete
方法。
现在,让我们谈谈如何更改用户的密码。
UserPrincipal insUserPrincipal = (UserPrincipal)lbUsers.SelectedItem;
insUserPrincipal.SetPassword("12345678");
MessageBox.Show("Password changed.");
您可以通过 GroupPrincipal
对象的 Members
属性获取组的成员。您可以将此属性用作枚举。要将用户添加到组,您应该将包含用户引用的 UserPrincipal
对象添加到此枚举中。移除用户也是同样的逻辑:您必须将该用户从枚举中移除。但是,不要忘记在对 GroupPrincipal
进行更改后执行其 Save
方法。您可以通过执行 UserPrincipal
对象的 GetGroups()
方法来列出用户所属的组。以下是一些示例。
//Listing groups members
GroupPrincipal insGroupPrincipal = (GroupPrincipal)lbGroups.SelectedItem;
List<principal> insListPrincipal = new List<principal>();
foreach (Principal p in insGroupPrincipal.Members)
{
insListPrincipal.Add(p);
}
//Listing users groups
UserPrincipal insUserPrincipal = (UserPrincipal)lbUsers.SelectedItem;
List<principal> insListPrincipal = new List<principal>();
foreach (Principal p in insUserPrincipal.GetGroups())
{
insListPrincipal.Add(p);
}
//Adding user to a group
UserPrincipal insUserPrincipal = (UserPrincipal)lbUsers.SelectedItem;
GroupPrincipal groupPrincipal =
GroupPrincipal.FindByIdentity(insPrincipalContext, group.GroupName);
if (groupPrincipal.Members.Contains(insPrincipalContext,
IdentityType.SamAccountName, insUserPrincipal.SamAccountName))
{
MessageBox.Show(insUserPrincipal.Name +
" is already a member of group " + group.GroupName);
return;
}
groupPrincipal.Members.Add(insUserPrincipal);
groupPrincipal.Save();
//Removing user from a group
UserPrincipal insUserPrincipal = (UserPrincipal)lbUsers.SelectedItem;
GroupPrincipal groupPrincipal =
GroupPrincipal.FindByIdentity(insPrincipalContext, group.GroupName);
groupPrincipal.Members.Remove(insUserPrincipal);
groupPrincipal.Save();
另外,这是用于验证用户凭据和筛选比较值的代码。
insPrincipalContext.ValidateCredentials("Tamer", "12345678");
parUserPrincipal.AdvancedSearchFilter.AccountExpirationDate(
DateTime.Now.Date.AddDays(10), MatchType.Equals);
parUserPrincipal.AdvancedSearchFilter.BadLogonCount(5, MatchType/span>.GreaterThanOrEquals);
如有 bug 报告和建议,请随时通过 oztamer@hotmail.com 与我联系。