Приветствую, коллеги!
Вопрос у меня такой:
Каждый пользователь, приходя утром на работу, вводит на своем компьютере пароль и авторизуется тем самым на сервере ActiveDirectory.
Соответственно, нужно организовать в конце дня сбор информации из AD — какой пользователь в какое время авторизовался и авторизовался ли вообще.
Эта информация должна быть получена из недр AD и занесена в базу данных MS SQL при помощи программы, написанной на .NET.
Соответственно, суть вопроса.
Какие библиотеки и классы задействовать для получения доступа к этой информации из AD и есть ли вообще возможность получить такую информацию от ActiveDirectory?
Здравствуйте, maxus78, Вы писали:
M>Приветствую, коллеги! M>Вопрос у меня такой: M>Каждый пользователь, приходя утром на работу, вводит на своем компьютере пароль и авторизуется тем самым на сервере ActiveDirectory. M>Соответственно, нужно организовать в конце дня сбор информации из AD — какой пользователь в какое время авторизовался и авторизовался ли вообще. M>Эта информация должна быть получена из недр AD и занесена в базу данных MS SQL при помощи программы, написанной на .NET. M>Соответственно, суть вопроса. M>Какие библиотеки и классы задействовать для получения доступа к этой информации из AD и есть ли вообще возможность получить такую информацию от ActiveDirectory?
Здравствуйте, maxus78, Вы писали:
M>Соответственно, нужно организовать в конце дня сбор информации из AD — какой пользователь в какое время авторизовался и авторизовался ли вообще.
По умолчанию в AD не ведётся аудит, если пользователь перелогинился несколько раз — запоминается последний вход в систему. Если устраивает, то смотрим обсуждение по теие
Спасибо всем отвечавшим. Однако при использовании красивой функции UserPrincipal.FindByLogonTime LastLogon содержит устаревшее на несколько дней значение. Гляделка студии показывает более похожее на реальность значение в UserPrincipal.PermittedWorkstations.inner.LastChange, но два последних члена private, а конструктор, например, PermittedWorkstations -- internal. Никто не знает, как студия показывает это значение (как до него добраться)?
Здравствуйте, akisawa, Вы писали:
A>Никто не знает, как студия показывает это значение (как до него добраться)?
Можно выгрести запросом через DirectorySearcher и посмотреть нужные свойства (см faq ).
Учтите, что результаты очень сильно зависят от политики домена и мании величия админа. Я бы не надеялся, что в любом домене вам вернут то, что попросите.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, akisawa, Вы писали:
A>>Никто не знает, как студия показывает это значение (как до него добраться)?
S>Можно выгрести запросом через DirectorySearcher и посмотреть нужные свойства (см faq ).
S>Учтите, что результаты очень сильно зависят от политики домена и мании величия админа. Я бы не надеялся, что в любом домене вам вернут то, что попросите.
А нельзя как-нибудь через WinNT, ведь Вы предлагаете через LDAP? У WinNT есть в свойствах логина LastLogin, а то, что предлагают мне админы даже имена логинов не содержит, только имена и фамилии пользователей, к которым по сорок с лишним свойств и ни одного подходящего.
Вообще на сервере ведётся протокол событий, там хранятся все попытки логона, успешные и неуспешные, судя по всему это не мессейджкью, так как таблицы сохраняются после перезагрузки (в SDK про это ничего нет).
Здравствуйте, maxus78, Вы писали:
M>Каждый пользователь, приходя утром на работу, вводит на своем компьютере пароль и авторизуется тем самым на сервере ActiveDirectory.
Это, кстати, не обязательно так. Если по каким-то причинам AD не доступен, юзер все равно сможет авторизоваться.
Здравствуйте, akisawa, Вы писали:
S>>Можно выгрести запросом через DirectorySearcher и посмотреть нужные свойства (см faq ).
A>А нельзя как-нибудь через WinNT, ведь Вы предлагаете через LDAP? У WinNT есть в свойствах логина LastLogin, а то, что предлагают мне админы даже имена логинов не содержит, только имена и фамилии пользователей, к которым по сорок с лишним свойств и ни одного подходящего.
WinNT — это древняя как не знаю кто фигня, годящаяся разве что на домены NT 4.0 и на локальные запросы.
Очевидно, грабли или в разрешениях, или в коде. Вы код приведите — завтра может чего подскажу.
A>Вообще на сервере ведётся протокол событий, там хранятся все попытки логона, успешные и неуспешные, судя по всему это не мессейджкью, так как таблицы сохраняются после перезагрузки (в SDK про это ничего нет).
Где ведётся? И, если он ведётся — почему не взять эти данные?
S>WinNT — это древняя как не знаю кто фигня, годящаяся разве что на домены NT 4.0 и на локальные запросы. S>Очевидно, грабли или в разрешениях, или в коде. Вы код приведите — завтра может чего подскажу.
Вот код, который выдаёт логоны очень с большой задержкой (от нескольких дней):
PrincipalContext principalContext = null;
principalContext = new PrincipalContext(ContextType.Domain, "servername.domen.ru", "userName", "password");
PrincipalSearchResult<UserPrincipal> result = null;
result = UserPrincipal.FindByLogonTime(principalContext, DateTime.Now,
MatchType.LessThanOrEquals);
DataTable table = new DataTable();
table.Columns.Add("Имя", Type.GetType("System.String"));
table.Columns.Add("Logon", Type.GetType("System.DateTime"));
foreach (UserPrincipal user in result)
{
Nullable<DateTime> logon = user.LastLogon;
string name = user.Name;
//DateTime change = user.PermittedWorkstations.inner.LastChange;
if (user.Surname!=null && logon!=null)
{
DateTime local = logon.Value.ToLocalTime();
table.Rows.Add(name, local);
}
}
grid.DataSource = table;
Вот выдаёт получше:
String myADSPath = "WinNT://servername.domen.ru,computer";
DirectoryEntry m_drentry = new DirectoryEntry(myADSPath);
DirectoryEntry m_secentry = m_drentry.Children.Find("sovelyev");
DateTime lLogin = Convert.ToDateTime(m_secentry.Properties["LastChange"].Value);
А вот попытался по-Вашей подсказке (про OU=Test сказал администратор):
String myADSPath = "LDAP://servername.domen.ru/OU=Test,DC=DOMEN,DC=ru";
DirectorySearcher search = new DirectorySearcher(m_drentry);
search.Filter = "(objectClass=user)";
SearchResultCollection searchResults = search.FindAll();
foreach (SearchResult searchResult in searchResults)
{
DirectoryEntry user = searchResult.GetDirectoryEntry();
DateTime lLogin = Convert.ToDateTime(user.Properties["LastLogin"].Value); // Value=null
}
A>>Вообще на сервере ведётся протокол событий, там хранятся все попытки логона, успешные и неуспешные, судя по всему это не мессейджкью, так как таблицы сохраняются после перезагрузки (в SDK про это ничего нет). S>Где ведётся? И, если он ведётся — почему не взять эти данные?
Windows Server 2003, администрирование -> просмотр событий (можно зайти через управление компьютером) -> безопасть: ведётся журнал событий в формате файл.evt, номер сообщения о логоне 540.
Здравствуйте, akisawa, Вы писали:
A>Вот код, который выдаёт логоны очень с большой задержкой (от нескольких дней):
Ок, завтра посмотрю.
A>Windows Server 2003, администрирование -> просмотр событий (можно зайти через управление компьютером) -> безопасть: ведётся журнал событий в формате файл.evt, номер сообщения о логоне 540.
Тогда вам нужен EventLog, или, если вам повезло и сервер у вас — 2008й, EventLogQuery.
Конечно, через LDAP оно понадёжнее, но и так сойдёт.
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, akisawa, Вы писали:
A>>Вот код, который выдаёт логоны очень с большой задержкой (от нескольких дней):
S>А так: S>
S> DirectorySearcher ds = new DirectorySearcher(
S> Domain.GetCurrentDomain().GetDirectoryEntry());
S> ds.Filter = "(objectClass=user)";
S> // необязательно.
S> ds.PropertiesToLoad.AddRange(new[] { "samaccountname", "lastlogontimestamp" });
S> foreach (SearchResult searchResult in ds.FindAll())
S> {
S> // если надо другие свойства:
S> // 1. убираем ds.PropertiesToLoad.AddRange...
S> // 2. ставим брякпойнт и смотрим через watch содержимое searchResult.Properties
S> Console.WriteLine((string)searchResult.Properties["samaccountname"][0]);
S> Console.WriteLine(DateTime.FromFileTime((long)searchResult.Properties["lastlogontimestamp"][0]));
S> }
S>
Спасибо за помощь, я тут чуть-чуть подправил (у нас не один контроллер в домене и нужны только OU=Test), но выдаваемые даты как у меня с UserPrincipal, то есть с большей задержкой, чем у WinNT. Сейчас тестирую EventLog. Данные есть, там таймштампы стоят по несколько штук в день на логин, всё подходит, один минус -- доступ очень медленный (мои логины программа искала почти час). Так что буду брать пользователей через Ваш пример, а их таймштампы через анализ (а он только построчный) ивентлога. Спасибо ещё раз. Хотя очень печально, что UserPrincipal не соджержит нормального времени.
A>Спасибо за помощь, я тут чуть-чуть подправил (у нас не один контроллер в домене и нужны только OU=Test), но выдаваемые даты как у меня с UserPrincipal, то есть с большей задержкой, чем у WinNT.
Однозначно у вас что-то не то с AD. У нас таймштампы актуальные. Посмотрите остальные свойства, может, найдёте что-нить.
A>Сейчас тестирую EventLog. Данные есть, там таймштампы стоят по несколько штук в день на логин, всё подходит, один минус -- доступ очень медленный (мои логины программа искала почти час).
Да, оно безбожно тормозит. Можно попробовать через WMI (сам не пробовал). Доменный сервер у вас не Win2008?
Здравствуйте, Sinix, Вы писали:
S>Здравствуйте, akisawa, Вы писали:
A>>Спасибо за помощь, я тут чуть-чуть подправил (у нас не один контроллер в домене и нужны только OU=Test), но выдаваемые даты как у меня с UserPrincipal, то есть с большей задержкой, чем у WinNT.
S>Однозначно у вас что-то не то с AD. У нас таймштампы актуальные. Посмотрите остальные свойства, может, найдёте что-нить.
A>>Сейчас тестирую EventLog. Данные есть, там таймштампы стоят по несколько штук в день на логин, всё подходит, один минус -- доступ очень медленный (мои логины программа искала почти час).
S>Да, оно безбожно тормозит. Можно попробовать через WMI (сам не пробовал). Доменный сервер у вас не Win2008?
Контроллеры (сервера) у нас все 2003. Но проблема решена. Accounts собираем через LDAP, а LastLogin берём максимальный из всех контроллеров через WinNT, этот штамп актуален. Ваш метод не проверял по всем контроллерам, а UserPrincipal не актуален.