如何从活动目录中获取用户列表?

Mik*_*ike 104 .net c# asp.net active-directory

如何从活动目录中获取用户列表?有没有办法提取用户名,名字,姓氏?我看到了一个类似的帖子:

 PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "YOURDOMAIN");
Run Code Online (Sandbox Code Playgroud)

我从未对活动目录做过任何事情,所以我完全迷失了.任何帮助将不胜感激!

Har*_*wok 218

如果您是Active Directory的新手,我建议您应该了解Active Directory如何首先存储数据.

Active Directory实际上是LDAP服务器.存储在LDAP服务器中的对象按层次存储.它与将文件存储在文件系统中非常相似.这就是它获得名称目录服务器和Active Directory的原因

Active Directory上的容器和对象可以由a指定distinguished name.尊贵的名字是这样的CN=SomeName,CN=SomeDirectory,DC=yourdomain,DC=com.与传统的关系数据库一样,您可以对LDAP服务器运行查询.它被称为LDAP查询.

有许多方法可以在.NET中运行LDAP查询.您可以使用的DirectorySearcherSystem.DirectoryServicesSearchRequestSystem.DirectoryServices.Protocol.

对于你的问题,因为你是问找到用户主体对象而言,我认为最直观的方法是使用PrincipalSearcherSystem.DirectoryServices.AccountManagement.你可以从谷歌轻松找到很多不同的例子.这是一个完全符合您要求的样本.

using (var context = new PrincipalContext(ContextType.Domain, "yourdomain.com"))
{
    using (var searcher = new PrincipalSearcher(new UserPrincipal(context)))
    {
        foreach (var result in searcher.FindAll())
        {
            DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
            Console.WriteLine("First Name: " + de.Properties["givenName"].Value);
            Console.WriteLine("Last Name : " + de.Properties["sn"].Value);
            Console.WriteLine("SAM account name   : " + de.Properties["samAccountName"].Value);
            Console.WriteLine("User principal name: " + de.Properties["userPrincipalName"].Value);
            Console.WriteLine();
        }
    }
}
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)

请注意,在AD用户对象上,有许多属性.特别是,givenName会给你First Name并且sn会给你Last Name.关于用户名.我认为你的意思是用户登录名.请注意,AD用户对象上有两个登录名.一个是samAccountName,也称为Windows 2000之前的用户登录名. userPrincipalName通常在Windows 2000之后使用.

  • 我正在使用相同的方法。我正在从 AD 获取所有用户(无过滤器)。问题是用户数量超过 150,000,因此可能需要长达 2 小时,是否有更快的方法来获取整个用户列表,或者我们是否可以优化上面的示例? (3认同)
  • 如果服务器不包含域,该怎么办 (2认同)
  • 如果当前计算机不属于域怎么办? (2认同)

ape*_*ira 21

如果您要过滤y活动帐户,请将此添加到Harvey的代码中:

 UserPrincipal userPrin = new UserPrincipal(context);
 userPrin.Enabled = true;
Run Code Online (Sandbox Code Playgroud)

第一次使用后.然后加

  searcher.QueryFilter = userPrin;
Run Code Online (Sandbox Code Playgroud)

在找到所有之前.这应该让你活跃.


Mik*_*keZ 7

用于浏览 AD 的 PrincipalContext 速度非常慢(仅用于 .ValidateCredentials,见下文),使用 DirectoryEntry 和 .PropertiesToLoad() 这样您只需为您需要的内容付费。

此处的过滤器和语法:https : //social.technet.microsoft.com/wiki/contents/articles/5392.active-directory-ldap-syntax-filters.aspx

此处的属性:https : //docs.microsoft.com/en-us/windows/win32/adschema/attributes-all

using (var root = new DirectoryEntry($"LDAP://{Domain}"))
{
    using (var searcher = new DirectorySearcher(root))
    {
        // looking for a specific user
        searcher.Filter = $"(&(objectCategory=person)(objectClass=user)(sAMAccountName={username}))";
        // I only care about what groups the user is a memberOf
        searcher.PropertiesToLoad.Add("memberOf");

        // FYI, non-null results means the user was found
        var results = searcher.FindOne();

        var properties = results?.Properties;
        if (properties?.Contains("memberOf") == true)
        {
            // ... iterate over all the groups the user is a member of
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

干净,简单,快速。没有魔法,也没有对 .RefreshCache 的半记录调用以在 try/catch 中获取 tokenGroups 或 .Bind 或 .NativeObject 以验证凭据。

用于验证用户:

using (var context = new PrincipalContext(ContextType.Domain))
{
    return context.ValidateCredentials(username, password);
}
Run Code Online (Sandbox Code Playgroud)


Jor*_*dan 5

当然,这归功于@Harvey Kwok,但我只是想添加此示例,因为在我的情况下,我想获取实际的UserPrincipals列表。预先过滤此查询可能更有效,但是在我的小型环境中,将所有内容提取出来,然后根据需要从列表中进行过滤就更容易了。

根据您的需要,可能不需要强制转换为DirectoryEntry,但是UserPrincipal无法提供某些属性。

using (var searcher = new PrincipalSearcher(new UserPrincipal(new PrincipalContext(ContextType.Domain, Environment.UserDomainName))))
{
    List<UserPrincipal> users = searcher.FindAll().Select(u => (UserPrincipal)u).ToList();
    foreach(var u in users)
        {
            DirectoryEntry d = (DirectoryEntry)u.GetUnderlyingObject();
            Console.WriteLine(d.Properties["GivenName"]?.Value?.ToString() + d.Properties["sn"]?.Value?.ToString());
        }
}
Run Code Online (Sandbox Code Playgroud)