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

如何从活动目录获取用户列表?有没有办法提取用户名,名,姓?我在一篇类似的帖子中看到过这样的用法:

 PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "YOURDOMAIN");

我从来没有做任何活动目录,所以我完全迷失了。任何帮助将非常感谢!

241521 次浏览

包含 System.DirectoryServices.dll,然后使用下面的代码:

DirectoryEntry directoryEntry = new DirectoryEntry("WinNT://" + Environment.MachineName);
string userNames="Users: ";


foreach (DirectoryEntry child in directoryEntry.Children)
{
if (child.SchemaClassName == "User")
{
userNames += child.Name + Environment.NewLine   ;
}


}
MessageBox.Show(userNames);

If you are new to Active Directory, I suggest you should understand how Active Directory stores data first.

ActiveDirectory 实际上是一个 LDAP 服务器。存储在 LDAP 服务器中的对象按层次结构存储。这非常类似于将文件存储在文件系统中。这就是为什么它被命名为 目录服务器和活动 目录

ActiveDirectory 上的容器和对象可以由 distinguished name指定。这个著名的名字就像这个 CN=SomeName,CN=SomeDirectory,DC=yourdomain,DC=com。就像传统的关系数据库一样,你可以在 LDAP 服务器上运行查询。这叫做 LDAP 查询。

中运行 LDAP 查询的方法有很多。NET.您可以使用 System.DirectoryServices中的 DirectorySearcherSystem.DirectoryServices.Protocol中的 SearchRequest

对于您的问题,既然您要求特别查找用户主体对象,我认为最直观的方法是使用 System.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();

Note that on the AD user object, there are a number of attributes. In particular, givenName will give you the First Name and sn will give you the Last Name. About the user name. I think you meant the user logon name. Note that there are two logon names on AD user object. One is samAccountName, which is also known as pre-Windows 2000 user logon name. userPrincipalName is generally used after Windows 2000.

如果你想过滤 y 个活跃的帐户,把这个添加到 哈维的准则:

 UserPrincipal userPrin = new UserPrincipal(context);
userPrin.Enabled = true;

在第一次使用后。然后添加

  searcher.QueryFilter = userPrin;

在找到一切之前,这样你就能找到活跃的了。

当然,这里的功劳属于@Harvey Kwok,但我只是想添加这个示例,因为在我的例子中,我想得到一个实际的用户负责人列表。预先过滤这个查询可能更有效,但是在我的小环境中,从列表中提取所有内容然后根据需要进行过滤更容易。

根据您的需要,您可能不需要强制转换为 DirectoryEntry,但是有些属性不能从 UserPrime 获得。

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());
}
}

用于浏览 AD 的 PrincipalContext 慢得可笑(仅用于。(请参阅下文) ,改为使用 DirectoryEntry,并且。PropertiesToLoad () ,所以您只需要为您需要的东西付费。

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

属性如下: Https://learn.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
}
}
}

干净,简单,快速。没有魔法,没有记录在案的电话。RefreshCache 以获取标记组或。绑定还是。在 try/catch 中验证凭据。

用于验证用户:

using (var context = new PrincipalContext(ContextType.Domain))
{
return context.ValidateCredentials(username, password);
}