检查是否启用了UserPrincipal

本文关键字:UserPrincipal 启用 是否 检查 | 更新日期: 2023-09-27 18:17:23

我正在使用c#代码来查询活动目录。我遇到的主要问题是确定一个帐户是否已被禁用。浏览许多在线文章,似乎不能完全依赖属性UserPrincipal。Enabled用于确定用户帐户是否已启用。很公平,因为它是一个可空的布尔值,但是当AD管理员禁用帐户时,它似乎被设置为false。我遇到的问题是,当我查询客户端的AD时,我发现大多数用户帐户UserPrincipal对象对此属性返回false。因此,当我使用以下代码检查一个帐户是否被禁用时:

private bool IsUserEnabled(UserPrincipal userPrincipal)
{
        bool isEnabled = true;
        if (userPrincipal.AccountExpirationDate != null)
        {
            // Check the expiration date is not passed.
            if (userPrincipal.AccountExpirationDate <= DateTime.Now)
            {
                Log.DebugFormat("User {0} account has expired on {1}", userPrincipal.DisplayName, userPrincipal.AccountExpirationDate.Value);
                isEnabled = false;
            }
        }
        if (userPrincipal.IsAccountLockedOut())
        {
            isEnabled = false;
            Log.DebugFormat("User {0} account is locked out", userPrincipal.DisplayName);
        }
        if (userPrincipal.Enabled != null)
        {
            isEnabled = userPrincipal.Enabled.Value;
            Log.DebugFormat("User {0} account is Enabled is set to {1}", userPrincipal.DisplayName, userPrincipal.Enabled.Value);
        }
        return isEnabled;
}

由于userPrincipal.Enabled检查,大多数帐户显示为禁用。

但是,如果我忽略这一点,只依赖于帐户到期日期和帐户锁定属性,那么我可能会错过使用Active Directory中的复选框禁用帐户而不设置帐户到期日期的人。

所有enabled返回false的帐户实际上是可以登录到域的活动帐户。

如何检查帐户是否实际启用?

检查是否启用了UserPrincipal

我遇到了一个类似的问题,同样感到困惑!

我最初使用System.DirectoryServices.DirectorySearcher来搜索禁用用户。AD用户记录的状态(禁用、锁定、密码过期等)存储在UserAccountControl属性中。您可以向DirectorySearcher传递一个过滤器,通过指定UserAccountControl属性作为过滤器的一部分来定位(比方说)禁用的帐户。

我从来都不喜欢这种方法,因为它相当于使用一个魔术字符串和一些魔术数字来构建查询;例如,这是用于定位禁用帐户的过滤器:

 var searcher = new DirectorySearcher(dirEntry)
            {
                Filter = "(UserAccountControl:1.2.840.113556.1.4.803:=2)",
                PageSize = 50
            };

当我切换到使用UserPrincipal时,我很高兴看到这个很方便的"Enabled"属性在类上。至少在我意识到它没有返回与DirectorySearcher过滤器将返回的相同的值之前是这样。

不幸的是,我能找到的唯一可靠的方法来确定帐户是否实际启用是挖掘底层DirectoryEntry对象,并直接去检查UserAccountControl属性,即:

var result = (DirectoryEntry)userPrincipal.GetUnderlyingObject();
var uac = (int)result.Properties["useraccountcontrol"].Value;
var isEnabled = !Convert.ToBoolean(uac & 2);

注意- UserAccountControl属性是一个"flags" enum;UserAccountControl属性的所有可能值可以在这里找到:https://msdn.microsoft.com/en-us/library/aa772300(v=vs.85).aspx

我最终将上面的代码片段构建为一个小扩展方法;幸运的是,做这个额外的工作来检索UserAccountControl属性并没有明显减慢我的AD查询。

我通过展开结果得到了一个解决方案,然后到基数并展开基数。您将在那里看到enabled属性。然后右键单击表达式并添加到watch,并将watch表达式复制到我的代码中。

  using (var context = new PrincipalContext(ContextType.Domain, "xyz.com", "Administrator", "xyz123"))
        {
            using (var searcher = new PrincipalSearcher(new UserPrincipal(context)))
            {
             foreach (var result in searcher.FindAll())
                {
                  DirectoryEntry de = result.GetUnderlyingObject() as DrectoryEntry;
             foreach (String key in de.Properties.PropertyNames)
                {
                   Console.WriteLine(key + " : " + de.Properties[key].Value);
                }
               Console.WriteLine("Enabled: "    +((System.DirectoryServices.AccountManagement.AuthenticablePrincipal)(result)).Enabled);
               Console.WriteLine("First Name: " + de.Properties["givenName"].Value);
                    }
                 }
             }
        Console.ReadLine();

((System.DirectoryServices.AccountManagement.AuthenticablePrincipal)(result)).Enabled在用户列表中为true或false

我可以告诉你在我的一个应用程序中什么对我有用。下面是我的应用程序的一个片段:

using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, "domain.com"))
{
    using (UserPrincipal user = UserPrincipal.FindByIdentity(pc, "Doe, John"))
    {
        Console.Out.Write(user.Enabled);
    }
}

对于我来说,这可以准确地返回帐户是否启用。