Фильтр DirectorySearcher, как ограничить на основе последних 30 дней - PullRequest
0 голосов
/ 07 ноября 2018

Я ищу Active Directory для пользователей в определенном подразделении. Я получаю только пользователей, которые вошли в систему за последние 30 дней.

Мой поисковый фильтр Запрос:

string query = "(&(objectCategory=person)(objectClass=user)((lastLogon<=" + new DateTime(DateTime.Now.AddDays(-30).Ticks) + ")(mail=*))";

Я получаю, что поисковый фильтр недействителен Я использовал:

string query = "(&(objectCategory=person)(objectClass=user)((lastLogon=*)(mail=*))";

без ошибок

Я изменил последний вход в систему следующим образом:

(lastLogon<=1)

Я вызываю метод, который делает это

public static DataTable GetADusers() {
    try {
        string ou = "OU";

        using(PrincipalContext ctx = new PrincipalContext(ContextType.Domain, Environment.UserDomainName, ou)) {
            UserPrincipal user = new UserPrincipal(ctx);
            using(PrincipalSearcher ps = new PrincipalSearcher(user)) {
                DataTable results = new DataTable();

                results.Columns.Add("DisplayName ");
                results.Columns.Add("FirstName");
                results.Columns.Add("Initial");
                results.Columns.Add("LastName");
                results.Columns.Add("mail");
                results.Columns.Add("SamAccountName");
                results.Columns.Add("DistinguishedName");
                results.Columns.Add("lastLogon");

                int count = 0;

                int ctNull = 0;

                foreach(Principal p in ps.FindAll()) {
                    UserPrincipal u = p as UserPrincipal;
                    if (u != null) {
                        DirectoryEntry entry = (DirectoryEntry) p.GetUnderlyingObject();
                        DirectorySearcher search = new DirectorySearcher(entry);

                        string query = "(&(objectCategory=person)(objectClass=user)((lastLogon<=" + new DateTime(DateTime.Now.AddDays( - 30).Ticks) + ")(mail=*))";

                        search.Filter = query;
                        search.PropertiesToLoad.Add("DisplayName");
                        search.PropertiesToLoad.Add("GivenName");
                        search.PropertiesToLoad.Add("Initials");
                        search.PropertiesToLoad.Add("sn");
                        search.PropertiesToLoad.Add("mail");
                        search.PropertiesToLoad.Add("SamAccountName");
                        search.PropertiesToLoad.Add("DistinguishedName");
                        search.PropertiesToLoad.Add("lastLogon");

                        SearchResultCollection mySearchResultColl = search.FindAll();

                        foreach(SearchResult sr in mySearchResultColl) {
                            DataRow dr = results.NewRow();
                            DirectoryEntry de = sr.GetDirectoryEntry();
                            dr["EmployeeID"] = de.Properties["EmployeeID"].Value;
                            dr["DisplayName "] = de.Properties["DisplayName"].Value;
                            dr["FirstName"] = de.Properties["GivenName"].Value;
                            dr["Initial"] = de.Properties["Initials"].Value;
                            dr["LastName"] = de.Properties["sn"].Value;
                            dr["mail"] = de.Properties["mail"].Value;
                            dr["SamAccountName"] = de.Properties["SamAccountName"].Value;
                            dr["DistinguishedName"] = de.Properties["DistinguishedName"].Value;
                            //prepare for last logon
                            if (de.Properties["lastLogon"] != null && de.Properties["lastLogon"].Count > 0) {
                                Int64 lastLogonThisServer = new Int64();
                                IADsLargeInteger lgInt = (IADsLargeInteger) de.Properties["lastLogon"].Value;
                                lastLogonThisServer = ((long) lgInt.HighPart << 32) + lgInt.LowPart;
                                dr["lastLogon"] = DateTime.FromFileTime(lastLogonThisServer).ToString();
                            }
                            else {
                                dr["lastLogon"] = DateTime.MinValue.ToString();
                                ctNull++;
                            }

                            results.Rows.Add(dr);
                            count++;

                        }

                    }
                }
                Console.WriteLine(count);
                Console.WriteLine("Null");
                Console.WriteLine(ctNull);

                return results;
            }

        }
    }
    catch(NullReferenceException ex) {
        Console.WriteLine("data error" + ex);
        DataTable dt = new DataTable();
        return dt;
    }
}

Вышеуказанная функция работает хорошо! Там должен быть способ проверить, если последний вход в систему старше 30 дней. Буду признателен за любую помощь. Спасибо!

Ответ ниже правильный, спасибо

Мне пришлось добавить следующий код для помещения данных в базу данных:

            if (de.Properties["LastLogonTimestamp"] != null && de.Properties["LastLogonTimestamp"].Count > 0)
                                {
                                    Int64 lastLogonDateThisServer = new Int64();
                                    IADsLargeInteger lgInt = (IADsLargeInteger)de.Properties["LastLogonTimestamp"].Value;
                                    lastLogonDateThisServer = ((long)lgInt.HighPart << 32) + lgInt.LowPart;
                                    dr["LastLogonTimestamp"] = DateTime.FromFileTime(lastLogonDateThisServer).ToString();

                                }
                                else
                                {

                                    dr["LastLogonTimestamp"] = DateTime.MinValue.ToString();
                                    ctNull++;
                                }

Я поместил его под последним логином Для фильтра запросов: мне пришлось повернуть знак <, чтобы получить данные с этого 30-дневного значения. </p>

                            string query = "(&(objectCategory=person)(objectClass=user)(!userAccountControl:1.2.840.113556.1.4.803:=2)(!userAccountControl:1.2.840.113556.1.4.803:=65536)(userAccountControl:1.2.840.113556.1.4.803:=262144)(userPrincipalName=1*@mil)(lastlogon>=" + DateTime.Now.AddDays(-90).ToFileTime() + ")(lastLogonTimestamp>=" + DateTime.Now.AddDays(-90).ToFileTime() + ")(mail=*))";

1 Ответ

0 голосов
/ 07 ноября 2018

В вашем запросе у вас есть две круглые скобки перед lastLogon, когда они вам не нужны:

((lastLogon<=...

Вот почему вы получаете сообщение об ошибке «фильтр поиска недействителен». Это должно быть:

(lastLogon<=...

Но вы также неверно рассчитываете значение. У вас есть это:

new DateTime(DateTime.Now.AddDays( - 30).Ticks)

Но lastLogon не использует галочки.

Позже в своем коде вы используете FromFileTime для считывания lastLogon. Аналогично, вы можете использовать ToFileTime для преобразования даты в формат, который вы можете использовать в запросе. Как это:

DateTime.Now.AddDays(-30).ToFileTime()

Но имейте в виду, что lastLogon не реплицируется - он точен только на последнем контроллере домена, с которым аутентифицировался пользователь. Поэтому, если в вашем домене имеется более одного контроллера домена, вы не получите точное значение для большинства учетных записей.

Атрибут lastLogonTimestamp был создан именно по этой причине. Он повторяется по крайней мере каждые 2 недели, поэтому вы знаете, что значение является точным в течение 2 недель. Вы можете использовать тот же формат для этого:

string query = "(&(objectCategory=person)(objectClass=user)(lastLogonTimestamp<="
    + DateTime.Now.AddDays(-30).ToFileTime() + ")(mail=*))";

Подробнее об атрибуте lastLogonTimestamp можно прочитать здесь: https://blogs.technet.microsoft.com/askds/2009/04/15/the-lastlogontimestamp-attribute-what-it-was-designed-for-and-how-it-works/

...