如何从活动目录中获取用户列表?有没有办法提取用户名,名字,姓氏?我看到了一个类似的帖子:
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, "YOURDOMAIN");
我从未对活动目录做过任何事情,所以我完全迷失了。任何帮助将不胜感激!
答案 0 :(得分:205)
如果您不熟悉Active Directory,我建议您应该了解Active Directory如何首先存储数据。
Active Directory实际上是一个LDAP服务器。存储在LDAP服务器中的对象按层次存储。它与将文件存储在文件系统中非常相似。这就是为什么它得到了名称目录服务器和Active 目录
Active Directory上的容器和对象可以由distinguished name
指定。专有名称与此CN=SomeName,CN=SomeDirectory,DC=yourdomain,DC=com
类似。与传统的关系数据库一样,您可以对LDAP服务器运行查询。它被称为LDAP查询。
有许多方法可以在.NET中运行LDAP查询。您可以使用System.DirectoryServices
中的DirectorySearcher或System.DirectoryServices.Protocol
中的SearchRequest。
对于您的问题,由于您要求专门查找用户主体对象,我认为最直观的方法是使用System.DirectoryServices.AccountManagement
中的PrincipalSearcher。你可以从谷歌轻松找到很多不同的例子。这是一个完全符合您要求的样本。
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();
请注意,在AD用户对象上,有许多属性。特别是,givenName
将为您提供First Name
,而sn
将为您提供Last Name
。关于用户名。我认为你的意思是用户登录名。请注意,AD用户对象上有两个登录名。一个是samAccountName
,也称为Windows 2000以前的用户登录名。 userPrincipalName
通常在Windows 2000之后使用。
答案 1 :(得分:21)
如果您要过滤y个活动帐户,请将此添加到Harvey的代码中:
UserPrincipal userPrin = new UserPrincipal(context);
userPrin.Enabled = true;
首次使用后。然后添加
searcher.QueryFilter = userPrin;
之前找到所有。这应该让你成为活跃的。
答案 2 :(得分:5)
用于浏览 AD 的 PrincipalContext 速度非常慢(仅用于 .ValidateCredentials,见下文),请改用 DirectoryEntry 和 .PropertiesToLoad(),因此您只需为您需要的内容付费。
这里的属性: 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
}
}
}
干净、简单、快速。没有魔法,没有对 .RefreshCache 的半记录调用来获取 tokenGroups 或在 try/catch 中调用 .Bind 或 .NativeObject 以验证凭据。
用于验证用户:
using (var context = new PrincipalContext(ContextType.Domain))
{
return context.ValidateCredentials(username, password);
}
答案 3 :(得分:4)
当然可以归功于@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());
}
}
答案 4 :(得分:1)
包含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);