Active Directory 在 Windows 服务中获取 Locked/Unlocked 状态

Active Directory Acquiring Locked/Unlocked status in a Windows Service

我正在创建一个 Windows 服务,它获取本地域 TRY.local 中所有 Active Directory 帐户的 Locked/Unlocked 状态。 即使名为 user1 的帐户被锁定,它也会为 IsAccountLocked().

提供 false
using (var context = new PrincipalContext(ContextType.Domain, "TRY.local"))
{
    using (var searcher = new PrincipalSearcher(new UserPrincipal(context)))
    {
        foreach (var result in searcher.FindAll())
        {
            DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
            Library.WriteErrorLog("First Name: " + de.Properties["givenName"].Value);
            try{
                string name = (string)de.Properties["samaccountname"].Value;
                PrincipalContext ctx = new PrincipalContext(ContextType.Domain,"TRY.local","CN="+name+",OU=Users,DC=TRY,DC=local","administrator","password");
                UserPrincipal usr = UserPrincipal.FindByIdentity(ctx, name);
                if(usr!=null){
                    Library.WriteErrorLog("IsAccountLockedOut\t"+usr.IsAccountLockedOut());
                }
                usr.Dispose();
                ctx.Dispose();
            }
        catch(Exception e){                                         
            Library.WriteErrorLog(e);
        }
    }
}

我也试过了

using (var context = new PrincipalContext(ContextType.Domain, "TRY.local"))
{
    using (var searcher = new PrincipalSearcher(new UserPrincipal(context)))
    {
        foreach (var result in searcher.FindAll())
        {
            DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
            Library.WriteErrorLog("SAM Account Name : " + de.Properties["samaccountname"].Value);
            int uc = Convert.ToInt32(de.Properties["userAccountControl"][0]);
            const int ADS_LOCKOUT = 0x00000010;
            bool account_LockedOut = (uc & ADS_LOCKOUT)==ADS_LOCKOUT;
            Library.WriteErrorLog("IsAccountLockedOut : "+account_LockedOut);                                       
        }
    }
}

WriteErrorLog(string abc) 将 abc 写入文本文件

我是 Active Directory 的新手,如果能得到有关此问题的指导,我将不胜感激。 提前致谢!

您必须拥有有效的网络凭据才能查询 Active Directory。

当服务 运行 作为本地服务时,它没有网络凭据 - 它只能在本地系统上运行。如果您需要网络凭据,请将服务配置为 运行 作为网络服务。 (如果您需要本地计算机的管理员访问权限,请使用本地系统;它具有网络凭据和本地管理员访问权限。)

作为网络服务或本地系统的服务 运行 在访问网络时使用计算机的 Active Directory 帐户,即,如果计算机名为 PLUGH,则用于访问网络的用户名是PLUGH$.

我发现当 UserPrincipal 对象用于获取帐户的锁定状态时,整个 LDAP 路径 直到组织用户所在的单位 (OU) 应与管理员登录名和密码一起作为参数提供给 PrincipalContext。

例如:

using (var context = new PrincipalContext(ContextType.Domain, "TRY.local"))
{
    using (var searcher = new PrincipalSearcher(new UserPrincipal(context)))
    {
        foreach (var result in searcher.FindAll())
        {
            DirectoryEntry de = result.GetUnderlyingObject() as DirectoryEntry;
            string path = de.Path;
            var offset = path.IndexOf('/');
            offset = path.IndexOf('/', offset+1);
            offset = path.IndexOf('/', offset+1);
            path = path.Substring(offset+1);
            string user_id = Convert.ToString(de.Properties["samaccountname"].Value); 

            PrincipalContext ctx = new PrincipalContext(ContextType.Domain,
                                       "TRY.local",
                                       path,
                                       "administrator",
                                       "password");

为了使用 UserPrincipal,我们现在将 ctx 和 user_id 作为参数传递给 UserPrincipal.FindByIdentity(PrincipalContext, string) 方法。

字符串路径最终将包含:"CN=User,OU=USERS,OU=DEPARTMENT,DC=SERVER,DC=COM"

UserPrincipal user_locked = UserPrincipal.FindByIdentity(ctx, username);
if (user_locked != null) {
    if (user_locked.IsAccountLockedOut()){
       user_locked.UnlockAccount();                                         
    }
    user_locked.Dispose();
    Console.WriteLine("Unlocked");
}
ctx.Dispose();