在AD中查找用户帐户是否已启用或禁用

12

我需要查找AD中用户账户是启用还是禁用的状态。

我找不到标志或属性"userAccountControl",是否可以使用USERPRINCIPAL类实现?

        drop_persona1.Items.Clear();
        string valor = drop_area.SelectedValue;

            List<string> allUsers = new List<string>();

       PrincipalContext ctx2 = new PrincipalContext(ContextType.Domain, "xxxxxxxx",
                                                        valor);


            UserPrincipal qbeUser2 = new UserPrincipal(ctx2);
            qbeUser2.Enabled = true; // activo para autenticacion

            PrincipalSearcher srch2 = new PrincipalSearcher(qbeUser2);
            srch2.QueryFilter = qbeUser2;    

            foreach (var found2 in srch2.FindAll().OrderBy(x=> x.DisplayName))
            {
                ListItem lst_user = new ListItem(found2.DisplayName, found2.SamAccountName);
                drop_persona1.Items.Insert(drop_persona1.Items.Count, lst_user);
            }

        //}
    }

敬礼


qbeUser2.Enabled = true; 应该就足够了。 - Hossein Narimani Rad
2个回答

16

如果您只需要确定用户是否启用或禁用,可以使用以下方法更简单地完成:

PrincipalContext context = new PrincipalContext(ContextType.Domain);
UserPrincipal user = UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, searchTextBox.Text.Trim());

if(user.Enabled == true) MessageBox.Show("Account enabled!");
else MessageBox.Show("Account disabled!");

6
到目前为止,在我的测试中,这个答案似乎与第一个答案的效果相同,但表现更出色。我有一段代码,可以查询一个组织单位的所有用户和组,并检查它们的禁用状态。其中一个环境有大约40,000个用户。我尝试了接受的答案和这个答案。接受的答案的性能大约是80分钟。而这个答案的性能是1分钟。 - Keith Kurak
您需要管理员权限执行此操作吗? - Muflix
此外,当您看到user.Enabled == true时,请不要感到困惑,您真正需要编写的是这样的代码:if(user.Enabled)是行不通的,因为Enabled属性是可空的。 - dezox

16

我没有测试过这个答案,但我相信它应该可以工作。

1) 使用以下方法获取目录条目��象 -

UserPrincipal qbeUser2 = new UserPrincipal(ctx2);
var dirEntry = qbeUser2.GetUnderlyingObject() as DirectoryEntry;

2)然后,通过以下方式检查帐户是否已禁用状态 -

var status = IsAccountDisabled(dirEntry);
public static bool IsAccountDisabled(DirectoryEntry user)
        {
            string Uac = "userAccountControl";
            if (user.NativeGuid == null) return false;

            if (user.Properties[Uac] != null && user.Properties[Uac].Value != null)
            {
                var userFlags = (UserFlags)user.Properties[Uac].Value;
                return userFlags.Contains(UserFlags.AccountDisabled);
            }

            return false;
        }

3) 这是枚举类型 UserFlags -

[Flags]
public enum UserFlags
{
    // Reference - Chapter 10 (from The .NET Developer's Guide to Directory Services Programming)

    Script = 1,                                     // 0x1
    AccountDisabled = 2,                            // 0x2
    HomeDirectoryRequired = 8,                      // 0x8
    AccountLockedOut = 16,                          // 0x10
    PasswordNotRequired = 32,                       // 0x20
    PasswordCannotChange = 64,                      // 0x40
    EncryptedTextPasswordAllowed = 128,             // 0x80
    TempDuplicateAccount = 256,                     // 0x100
    NormalAccount = 512,                            // 0x200
    InterDomainTrustAccount = 2048,                 // 0x800
    WorkstationTrustAccount = 4096,                 // 0x1000
    ServerTrustAccount = 8192,                      // 0x2000
    PasswordDoesNotExpire = 65536,                  // 0x10000 (Also 66048 )
    MnsLogonAccount = 131072,                       // 0x20000
    SmartCardRequired = 262144,                     // 0x40000
    TrustedForDelegation = 524288,                  // 0x80000
    AccountNotDelegated = 1048576,                  // 0x100000
    UseDesKeyOnly = 2097152,                        // 0x200000
    DontRequirePreauth = 4194304,                   // 0x400000
    PasswordExpired = 8388608,                      // 0x800000 (Applicable only in Window 2000 and Window Server 2003)
    TrustedToAuthenticateForDelegation = 16777216,  // 0x1000000
    NoAuthDataRequired = 33554432                   // 0x2000000
}

更新

这是完整的代码,在AD上测试通过,我的测试结果很好。

using System;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;

namespace DisableUsers
{
internal class Program
{
    private static void Main()
    {
        const string sAMAccountName = "vikas"; // The sAMAccountName of AD user
        var principalContext = new PrincipalContext(ContextType.Domain, "domainNameHere", "AdminUser", "AdminPass");
        var userPrincipal = UserPrincipal.FindByIdentity(principalContext, sAMAccountName);

        if (userPrincipal != null)
        {
            var dirEntry = userPrincipal.GetUnderlyingObject() as DirectoryEntry;
            var status = IsAccountDisabled(dirEntry);
            Console.WriteLine(status ? "Account {0} is disabled." : "Account {0} is enabled.", sAMAccountName);
        }
        else
        {
            Console.WriteLine("No user found for sAMAccountName '{0}'.", sAMAccountName);
        }

        Console.ReadLine();
    }

    public static bool IsAccountDisabled(DirectoryEntry user)
    {
        const string uac = "userAccountControl";
        if (user.NativeGuid == null) return false;

        if (user.Properties[uac] != null && user.Properties[uac].Value != null)
        {
            var userFlags = (UserFlags)user.Properties[uac].Value;
            return userFlags.Contains(UserFlags.AccountDisabled);
        }

        return false;
    }
}

public static class UserFlagExtensions
{
    /// <summary>
    /// Check if flags contains the specific user flag. This method is more efficient compared to 'HasFlag()'.
    /// </summary>
    /// <param name="haystack">The bunch of flags</param>
    /// <param name="needle">The flag to look for.</param>
    /// <returns>Return true if flag found in flags.</returns>
    public static bool Contains(this UserFlags haystack, UserFlags needle)
    {
        return (haystack & needle) == needle;
    }
}

[Flags]
public enum UserFlags
{
    Script = 1,                                     // 0x1
    AccountDisabled = 2,                            // 0x2
    HomeDirectoryRequired = 8,                      // 0x8
    AccountLockedOut = 16,                          // 0x10
    PasswordNotRequired = 32,                       // 0x20
    PasswordCannotChange = 64,                      // 0x40
    EncryptedTextPasswordAllowed = 128,             // 0x80
    TempDuplicateAccount = 256,                     // 0x100
    NormalAccount = 512,                            // 0x200
    InterDomainTrustAccount = 2048,                 // 0x800
    WorkstationTrustAccount = 4096,                 // 0x1000
    ServerTrustAccount = 8192,                      // 0x2000
    PasswordDoesNotExpire = 65536,                  // 0x10000 (Also 66048 )
    MnsLogonAccount = 131072,                       // 0x20000
    SmartCardRequired = 262144,                     // 0x40000
    TrustedForDelegation = 524288,                  // 0x80000
    AccountNotDelegated = 1048576,                  // 0x100000
    UseDesKeyOnly = 2097152,                        // 0x200000
    DontRequirePreauth = 4194304,                   // 0x400000
    PasswordExpired = 8388608,                      // 0x800000 (Applicable only in Window 2000 and Window Server 2003)
    TrustedToAuthenticateForDelegation = 16777216,  // 0x1000000
    NoAuthDataRequired = 33554432                   // 0x2000000
}
}

“在调用此方法之前,必须持久化Principal对象。” System.InvalidOperationException---在var dirEntry = qbeUser2.GetUnderlyingObject() as DirectoryEntry; 中。 - Ivan Diaz Salas
@IvanDiaz 我已经更新了答案。希望它能像在我的端上一样工作。 - Vikram Singh Saini
有没有可能在不使用“userAccountControl”的情况下检查状态? - Shesha
@Shesha 我不知道其他的方法。但是你尝试过Brian Overby提供的以下解决方案吗? - Vikram Singh Saini
属性名称"userAccountControl"在我最新的Windows 10更新版本中无法使用。看起来他们将其重命名为"UserFlags"。 "UserFlags"的值/标志与此处描述的方式完全相同。 - HooNose

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接