【问题标题】:Active directory - get list of users with password expiring soonActive Directory - 获取密码即将到期的用户列表
【发布时间】:2017-12-20 02:34:07
【问题描述】:

我需要从 Active Directory 中获取密码即将到期(比如 5 天)的用户列表。

我需要通过向DirectorySearcher 添加过滤器来做到这一点,因为它会最快。我已将samaccountname 模式添加到过滤器中,但我不知道如何将pwdLastSet 添加到其中。理想情况下,过滤器会将用户列表减少到仅满足密码过期条件的用户。

        using (DirectoryEntry searchRoot = GetXYZAccountOU())
        {
            DirectorySearcher ds = new DirectorySearcher(searchRoot);
            ds.SearchScope = SearchScope.Subtree;

            ds.Filter = "(&" +                                
                            "(samaccountname=XYZ*)"
             + ")";


            SearchResultCollection result = ds.FindAll();

            foreach (SearchResult searchResult in result)
            {
                var de = searchResult.GetDirectoryEntry();
                //long pwdLastSetVal = (long)de.Properties["pwdLastSet"][0];

                //Console.WriteLine(de.Properties["displayName"].Value + ": " + DateTime.FromFileTimeUtc(pwdLastSetVal));
                Console.WriteLine(de.Properties["displayName"].Value);
            }

            Console.Read();
        }

这里的 XYZ 是我的用户samaccountname 的首字母。

如果我运行此代码,我可以获得displayName 和其他一些属性,但不能获得pwdLastSet 或计算属性msDS-UserPasswordExpiryTimeComputed,而我可以在Active Directory 浏览器中看到它们。

【问题讨论】:

  • 您最好使用 PrincipalContext 执行此操作,请在此处查看示例 stackoverflow.com/questions/5535829/…
  • 我知道我们可以使用 UserPrincipal 找到单个用户的密码到期日期,但我需要找到密码在几天后到期的用户列表。如果我得到所有用户的列表,然后遍历它们以找到每个用户的到期日期,从性能的角度来看,这将是非常糟糕的。
  • 您也可以这样做,您目前如何为单个用户执行此操作?做同样的事情,但在 for 循环或 foreach 循环内做。你需要跳出框框思考
  • @MethodMan 这将非常昂贵,因为这是多个 AD 查询。对于任何半体面的公司,基础设施团队将立即关闭该工具
  • @Danish 切换到较低级别的LdapQuery 类。然后,您可以指定要在查询中获取的属性。

标签: c# active-directory directorysearcher


【解决方案1】:

您必须提前知道密码的有效期,并查询pwdLastSet 属性。当然,日期是以一种奇怪的格式存储的。

假设它们的有效期为 30 天。然后你可以像这样构造查询:

var date = DateTime.Now.AddDays(-30).ToFileTime();
var query = $"(&(objectclass=user)(objectcategory=person)(!pwdlastset=0)(pwdlastset<={date})(!userAccountControl:1.2.840.113556.1.4.803:=65536))";

帐户可以设置为密码永不过期,因此您必须在查询中考虑到这一点。 userAccountControl 条件就是这样做的。

如果您不想在代码中使用幻数,您可以通过查看域根目录下的maxPwdAge 属性(存储在一种不同的、奇怪的格式):

var domain = new DirectoryEntry("LDAP://domain.com");
Int64 pwdAge = (Int64) domain.Properties["maxPwdAge"][0];
var maxPwdAge = pwdAge / -864000000000; //convert to days

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多