Я проверяю логины пользователей с помощью модуля python'ldap. Когда вход не удается, я получаю логин ldap.INVALID_CREDENTIALS, но это может быть либо из-за неправильного пароля, либо из-за того, что учетная запись заблокирована. Учетная запись блокируется после третьей попытки.
Я хотел бы определить, что учетная запись заблокирована, и сообщить об этом разочарованному пользователю, вместо того, чтобы выдать сообщение "недействительный вход".
В поисках решения я нашел:
Запрос LDAP, который я должен использовать для поиска заблокированных пользователей, следующий:
(&(objectClass=user)(lockoutTime>=1))
Или для конкретного пользователя:
(&(objectClass=user)(sAMAccountName=jabberwocky)(lockoutTime>=1))
Но это не работает, запрос каждый раз возвращает отсутствие результатов.
Значение ноль в lockoutTime
означает, что он не заблокирован. Поэтому вам следует попробовать следующее.
(&(objectClass=user)(!lockoutTime=0))
На самом деле, приведенный выше запрос все еще не является на 100% правильным. Если вы прочитаете мелкий шрифт из MSDN, Microsoft предлагает вам добавить атрибут Lockout-Time
к атрибуту Lockout-Duration
и затем сравнить его с текущим временем. Это потому, что существует такая вещь, как продолжительность блокировки. Как только длительность блокировки пройдет, пользователь будет разблокирован автоматически. Ноль в Lockout-Duration
означает, что учетная запись заблокирована навсегда, пока администратор не разблокирует ее.
См. эту статью MSDN
Значение этого атрибута сбрасывается только тогда, когда учетная запись входит в систему успешно. Это означает, что данное значение может быть ненулевым, но при этом учетная запись не заблокирована. Чтобы точно определить, является ли учетная запись заблокирована, вы должны прибавить к этому времени Lockout-Duration и сравнить полученный результат с текущим временем, учитывая местные часовые пояса и летнего времени.
lockoutTime
- это атрибут <not set>
, поэтому самый простой способ - использовать:
(&(objectClass=user)(lockoutDuration=*)))
для непустых записей.
Обновление:
Однако это значение также устанавливается, когда срок действия пароля истекает, пароль необходимо изменить и т.д.
Поэтому его необходимо отфильтровать:
UserPrincipal userPrincipal = new UserPrincipal(context);
bool isLocked = userPrincipal.IsAccountLockedOut();
чтобы получить случаи, когда пользователь был заблокирован из-за нарушения политики паролей, например, неправильного ввода пароля 5 раз.
Кроме того, я обнаружил, что lockoutTime не гарантируется для всех пользователей в AD (по крайней мере, в нашей конфигурации), но будет создан по достижении количества неудачных попыток блокировки. Поэтому при проверке заблокированных учетных записей также потребуется проверка на None или эквивалент.