Created by: ykmn
Code-review нашёл две MEDIUM-находки: сообщения об ошибке входа позволяли отличить "нет такого пользователя" от "неверный пароль" (плюс timing-side-channel через BCrypt), а AuthService.AuthRequired перечитывал и парсил ldap.yaml на каждый HTTP-запрос.
- AuthService/LdapAuthenticator: единое сообщение "Неверный логин или пароль" для local- и LDAP-провала входа; PasswordHasher.DummyHash выравнивает время BCrypt-проверки для несуществующих пользователей; реальная причина сохраняется в AuthException.LogDetail для лога.
- AuthService.GetLdapConfig: кэш LdapConfig с инвалидацией по mtime файла вместо чтения+парсинга YAML на каждый запрос.