在 C# 中通过示例查询锁定的帐户
Query by example for Locked Out Accounts in C#
我想使用示例查询来显示我的 OU 中所有被锁定的帐户。
我能够成功地对已启用的帐户和需要智能卡登录的帐户执行类似的操作。
出于某种原因,userPrincipal.IsAccountLockedOut()
的功能似乎与 userPrincipal.Enabled
不同
基本上,它似乎是一个方法而不是一个变量。
我在网上搜索过,但没有找到与此用例相关的任何相关答案或文档。
这是我的代码,目前:
bool enabled = true;
bool locked = false;
string firstName = "John";
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
UserPrincipal up = new UserPrincipal(ctx);
up.Enabled = enabled;
up.GivenName = firstName;
但是,up.IsAccountLockedOut() = locked;
不起作用。 locked = up.IsAccountLockedOut()
也不行
IsAccountLockedOut()
与 Enabled
的功能不同,因为它们是两个不同的东西:
- 帐户因多次错误密码尝试而被锁定。这是为了防止暴力破解密码。帐户通常会在一段时间后自动解锁。触发锁定的错误尝试次数和自动解锁前的时间可由域管理员配置。
- 禁用帐户 (
Enabled == false
) 是指管理员专门禁用了帐户。任何人都无法使用已禁用的帐户进行身份验证,即使他们知道正确的密码。
要查找被锁定的帐户,您需要查看 lockoutTime
属性。它存储帐户被锁定的时间。值为 0 表示未锁定。所以您想查找值大于 0 的帐户。这将是 LDAP 查询:
(&(objectCategory=person)(objectClass=user)(lockoutTime>=1))
您必须使用 >=1
,因为 LDAP 规范实际上不支持 >
。
我假设您问这个问题是因为您正在尝试使用 PrincipalSearcher
进行搜索,这限制了您根据 UserPrincipal
向您公开的属性进行搜索。由于 lockoutTime
属性未被 UserPrincipal
公开,因此您不能那样做。您必须直接使用 DirectorySearcher
(无论如何 PrincipalSearcher
在幕后使用)。这是一个输出用户名和锁定发生时间的示例:
var searcher = new DirectorySearcher() {
Filter = "(&(objectCategory=person)(objectClass=user)(lockoutTime>=1))",
PageSize = 1000, //make sure we get more than one page, if needed
PropertiesToLoad = { "sAMAccountName", "lockoutTime" } //which atrributes you want to use
};
using (var results = searcher.FindAll()) {
foreach (SearchResult result in results) {
var username = (string) result.Properties["sAMAccountName"][0];
var lockoutTime = DateTime.FromFileTime((long) result.Properties["lockoutTime"][0]);
Console.WriteLine($"{username} was locked out at {lockoutTime}");
}
}
就我个人而言,我已经完全停止使用 UserPrincipal
/PrincipalSearcher
,因为性能总是更差(有时不明显,有时绝对如此),有时您会遇到这样的情况反正不能用。我写了一篇关于在与 AD 交谈时获得最佳性能的文章,如果您有兴趣:Active Directory: Better performance
我想使用示例查询来显示我的 OU 中所有被锁定的帐户。
我能够成功地对已启用的帐户和需要智能卡登录的帐户执行类似的操作。
出于某种原因,userPrincipal.IsAccountLockedOut()
的功能似乎与 userPrincipal.Enabled
基本上,它似乎是一个方法而不是一个变量。
我在网上搜索过,但没有找到与此用例相关的任何相关答案或文档。
这是我的代码,目前:
bool enabled = true;
bool locked = false;
string firstName = "John";
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);
UserPrincipal up = new UserPrincipal(ctx);
up.Enabled = enabled;
up.GivenName = firstName;
但是,up.IsAccountLockedOut() = locked;
不起作用。 locked = up.IsAccountLockedOut()
IsAccountLockedOut()
与 Enabled
的功能不同,因为它们是两个不同的东西:
- 帐户因多次错误密码尝试而被锁定。这是为了防止暴力破解密码。帐户通常会在一段时间后自动解锁。触发锁定的错误尝试次数和自动解锁前的时间可由域管理员配置。
- 禁用帐户 (
Enabled == false
) 是指管理员专门禁用了帐户。任何人都无法使用已禁用的帐户进行身份验证,即使他们知道正确的密码。
要查找被锁定的帐户,您需要查看 lockoutTime
属性。它存储帐户被锁定的时间。值为 0 表示未锁定。所以您想查找值大于 0 的帐户。这将是 LDAP 查询:
(&(objectCategory=person)(objectClass=user)(lockoutTime>=1))
您必须使用 >=1
,因为 LDAP 规范实际上不支持 >
。
我假设您问这个问题是因为您正在尝试使用 PrincipalSearcher
进行搜索,这限制了您根据 UserPrincipal
向您公开的属性进行搜索。由于 lockoutTime
属性未被 UserPrincipal
公开,因此您不能那样做。您必须直接使用 DirectorySearcher
(无论如何 PrincipalSearcher
在幕后使用)。这是一个输出用户名和锁定发生时间的示例:
var searcher = new DirectorySearcher() {
Filter = "(&(objectCategory=person)(objectClass=user)(lockoutTime>=1))",
PageSize = 1000, //make sure we get more than one page, if needed
PropertiesToLoad = { "sAMAccountName", "lockoutTime" } //which atrributes you want to use
};
using (var results = searcher.FindAll()) {
foreach (SearchResult result in results) {
var username = (string) result.Properties["sAMAccountName"][0];
var lockoutTime = DateTime.FromFileTime((long) result.Properties["lockoutTime"][0]);
Console.WriteLine($"{username} was locked out at {lockoutTime}");
}
}
就我个人而言,我已经完全停止使用 UserPrincipal
/PrincipalSearcher
,因为性能总是更差(有时不明显,有时绝对如此),有时您会遇到这样的情况反正不能用。我写了一篇关于在与 AD 交谈时获得最佳性能的文章,如果您有兴趣:Active Directory: Better performance