65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 System.DirectoryServices.AccountManagement

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.88/5 (27投票s)

2009 年 7 月 21 日

CPOL

4分钟阅读

viewsIcon

306505

downloadIcon

8678

在本文中,我们将重点介绍如何使用 .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 对象的基类。它包含通用方法,例如 SaveDelete
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);
}

现在,让我们看看列出和筛选用户或组的逻辑。您可以轻松地看到 SearchGroupsSearchUsers 方法是相似的。最重要的一点是,对于组功能使用 GroupPrincipal,对于用户功能使用 UserPrincipal。并且,principal searcher 是提供搜索功能 的公共类。在将包含筛选器的对象(GroupPrincipalUserPrincipal)分配给该对象的 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 与我联系。

© . All rights reserved.