【问题标题】:Get just the Enabled Accounts from Active Directory仅从 Active Directory 中获取已启用的帐户
【发布时间】:2013-01-17 14:05:43
【问题描述】:

我正在使用System.DirectoryServices.AccountManagement.dll 处理 Active Directory 获取“域用户”组中的所有用户。

这将返回域中的所有用户,但我只需要获取已启用的用户。

这里是一些示例代码:

List<string> users = new List<string>();

PrincipalContext pcContext = GetPrincipalContext();

GroupPrincipal grp = GroupPrincipal.FindByIdentity(pcContext,
                               IdentityType.Name,
                               "Domain Users");

foreach (Principal user in grp.GetMembers(true).OfType<UserPrincipal>())
{
    if (user.Enabled != false)
    {
        users.Add(user.Name);
    }
}

其他组工作正常,但是当组是“域用户”时,Enabled 属性的值对于所有用户都是false。这使得如果不对每个用户进行进一步查询,就无法区分启用和禁用用户。

【问题讨论】:

  • 只需要账号名吗?是否需要使用 AccountManagement 命名空间?除了存储名称之外,您是否对 UserPrincipal 对象执行任何操作?我只是问,因为使用 DirectoryServices 命名空间和具有 LDAP 过滤器的 DirectorySearcher 可能会更好地满足您的要求,例如: (&(objectclass=user)(memberOf=CN=Domain Users,dc=company,dc=com)(! (userAccountControl:1.2.840.113556.1.4.803:=2))) 这将返回该组中启用的所有用户。
  • randcd:我更喜欢使用 AM 命名空间,因为它提供了非常简洁的 API。我当然可以使用 LDAP,但随后一切都变得更加复杂(尤其是在用户只是域用户的成员的情况下,因为它是他们的主要组,因为在这种情况下它没有在 memberOf 中列出)。
  • ForEach 循环中的“Principal”实际上应该是“UserPrincipal”——“Enabled”不是在 Princpal 对象上可访问的方法或属性。至少不在 .net 4.6.1 中。这一切都可以通过 System.DirectoryServices.AccountManagement 命名空间来完成。

标签: c# active-directory directoryservices account-management


【解决方案1】:

UserPrinciple 对象对此有一个 bool Enabled 属性。

http://msdn.microsoft.com/en-us/library/system.directoryservices.accountmanagement.userprincipal_properties.aspx

// Add this to GetUserDetails
objUserDetails.EmployeeId = UserPrinical.EmployeeId;


// Then condition the add to only add enabled
if (objUserDetails.Enabled) {
    objUserDetails.Add(GetUserDetails(p.Name));
}

【讨论】:

  • 这并不能解决问题,因为当被查询的组是“域用户”时,Enabled 属性似乎没有正确填充
【解决方案2】:

解决这个问题的方法可能是首先使用PrincipalSearcher类搜索启用用户,然后使用IsMemberOf()的主体方法

List<string> users = List<string>();
PrincipalContext pcContext = GetPrincipalContext();
GroupPrincipal grp = GroupPrincipal.FindByIdentity(pcContext, IdentityType.Name, "Domain Users");
UserPrincipal searchFilter = new UserPrincipal(pcContext){ Enabled = true }
PrincipalSearcher searcher = new PrincipalSearcher(searchFilter);
PrincipalSearchResult<Principal> results = searcher.FindAll();
foreach (Principal user in results)
    if (user.IsMemberOf(grp))
        users.Add(user.SamAccountName);

【讨论】:

    【解决方案3】:

    MSDN page of the Enabled property 上有一句话说:

    如果主体没有被持久化在存储中,这个属性返回 null。主体持久化后,默认启用设置取决于存储。 AD DS 和 AD LDS 存储在持久化新主体时禁用它们,而 SAM 在持久化新主体时启用它们。应用程序只能将此属性设置为一个值,然后才能将其持久化到存储中。

    如果默认为 false 可能是相关的?

    另外,MSDN 论坛上有一篇关于 UserPrincipal.Enabled returns False for accounts that are in fact enabled? 的帖子,听起来与您的问题非常相似。根据帖子,这里可能有一个解决方案:

    我想我误解了。无视我之前发的内容。我想我 知道发生了什么。 GetMembers 方法显然没有加载 用户主体数据。不知道有没有更好的解决办法 但以下工作(至少在我的广告上):

    foreach (UserPrincipal user in group.GetMembers(false))
    {
       UserPrincipal tempUser = UserPrincipal.FindByIdentity(context, user.SamAccountName);
       // use tempUser.Enabled
       // other code here
    }
    

    【讨论】:

    • 用户已经被持久化,所以你的答案的第一部分与问题无关。至于其余的,是的 - 我知道我可以做到 - 问题表明我们希望为 Enabled 属性 获得正确的值,而不必进行任何额外的查询(尤其是每个用户喜欢在那个 foreach 循环中)。您引用的帖子甚至说此解决方案太慢而无法使用。
    猜你喜欢
    • 1970-01-01
    • 2018-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多