【问题标题】:System.DirectoryServices.AccountManagement and returning an IEnumerable of Active Directory userSystem.DirectoryServices.AccountManagement 并返回 Active Directory 用户的 IEnumerable
【发布时间】:2018-04-11 23:40:07
【问题描述】:

我正在尝试查询 Active Directory 并返回一个 IEnumerable,但它具有 Title 和 EmailAddress 等属性,但在 PrincipalSearcher.Findll() 中没有显示这些属性。如果我使用 PrincipalSearcher.FindOne(),它有更多的属性(但仍然不是 Title),所以我试图弄清楚我在做什么不同或如何获取我需要的信息。我已经厌倦了谷歌试图找到更多信息,似乎 UserPrincipal.GetUnderlyingObject() 可能是票,但我不明白如何将其纳入 foreach 循环以便将其填充到列表中。

    public class ADUser
    {
        public string SamAccountName { get; set; }
        public string DisplayName { get; set; }
        public string Title { get; set; }

        public IEnumerable<ADUser> Get(string username)
        {
            var users = new List<ADUser>();

            var principalContext = new PrincipalContext(ContextType.Domain, "domain.com");
            var userPrincipal = new UserPrincipal(principalContext)
            {
                SamAccountName = username
            };

            var principalSearcher = new PrincipalSearcher(userPrincipal);

            foreach (var user in principalSearcher.FindAll())
            {
                users.Add(new ADUser
                {
                    SamAccountName = user.SamAccountName,
                    DisplayName = user.DisplayName,
                    //Title = user.Title //Won't work, no Title property
                });
            }

            return users;
        }
    }

这可行,但只返回 .FindOne() 的一小部分属性,但如果我执行 FindOne(),我将无法搜索部分用户名,例如“jsm”返回“John Smith”和“詹姆斯·斯莫斯”。

【问题讨论】:

标签: c# asp.net-mvc active-directory


【解决方案1】:

简短的回答是您可以这样做:

        foreach (var user in principalSearcher.FindAll())
        {
            var userDe = (DirectoryEntry) user.GetUnderlyingObject();
            users.Add(new ADUser
            {
                SamAccountName = user.SamAccountName,
                DisplayName = user.DisplayName,
                Title = userDe.Properties["title"]?.Value.ToString()
            });
        }

这是我不再使用 AccountManagement 命名空间的部分原因。它在后台使用DirectoryEntry 并隐藏了它的复杂性以使基本的事情对您来说更容易,但您仍然必须恢复为直接使用DirectoryEntry 来处理某些事情。而且它的执行速度实际上比直接使用DirectoryEntry/DirectorySearcher 要慢。

这是一个示例,说明如何通过DirectorySearcher 执行相同操作。它有点复杂,但我敢打赌你会发现它执行得更快:

public class ADUser
{
    public string SamAccountName { get; set; }
    public string DisplayName { get; set; }
    public string Title { get; set; }

    public IEnumerable<ADUser> Get(string username)
    {
        var users = new List<ADUser>();

        var search = new DirectorySearcher(
            new DirectoryEntry("LDAP://domain.com"),
            $"(&(objectClass=user)(objectCategory=person)(sAMAccountName={username}))",
            new [] { "sAMAccountName", "displayName", "title" } //The attributes you want to see
        ) {
            PageSize = 1000 //If you're expecting more than 1000 results, you need this otherwise you'll only get the first 1000 and it'll stop
        };

        using (var results = search.FindAll()) {
            foreach (SearchResult result in results)
            {
                users.Add(new ADUser
                {
                    SamAccountName = result.Properties.Contains("sAMAccountName") ? result.Properties["sAMAccountName"][0].ToString() : null,
                    DisplayName = result.Properties.Contains("displayName") ? result.Properties["displayName"][0].ToString() : null,
                    Title = result.Properties.Contains("title") ? result.Properties["title"][0].ToString() : null
                });
            }
        }
        return users;
    }
}

【讨论】:

  • 我猜当您按用户名搜索时,您永远不会期望超过 1000 个结果 :) 它只是让我失望,因为您要返回一个列表。无论如何,这是一件好事。
  • 当我尝试运行该代码时,出现错误:“ArgumentOutOfRangeException:索引超出范围。必须为非负数且小于集合的大小。参数名称:索引”在确切的用户名和部分用户名上。我认为这可能与“新 []”有关?
  • 我没有遇到任何异常。哪一行为您抛出异常?
  • 如果您希望它也适用于部分用户名,您必须在过滤器中添加*$"(&amp;(objectClass=user)(objectCategory=person)(sAMAccountName={username}*))"
  • ADUser.cs 的第 35 行,"users.Add(new ADUser" 行。
猜你喜欢
  • 1970-01-01
  • 2019-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多