ValidateCredentials возвращает true для неизвестного пользователя?

Я вижу какое-то странное поведение, используя PrincipalContext.ValidateCredentials. Настройка состоит из двух доменов Active Directory в родительской/дочерней настройке (поэтому у нас есть основной домен company.com и поддомен development.company.com).

Когда я проверяю учетные данные в отношении основного домена, ValidateCredentials ведет себя так, как ожидалось, возвращает true для хороших пар user/pass и false для чего-либо еще.

Однако, если я проверяю пользователя в поддомене, ValidateCredentials возвращает true как для хорошего имени пользователя/пароля, так и для недопустимых пользователей. Если я предоставляю действительного пользователя с недопустимым паролем, он правильно возвращает false.

Теперь я работаю над этим в настоящий момент, сначала выполняя UserPrincipal.FindByIdentity(), и если пользователь существует, а затем вызывает ValidateCredentials - но я хотел бы понять, что происходит.

Другим обходным решением, которое я рассмотрел, является передача имени пользователя через domain\username в качестве записи MSDN для состояний ValidateCredentials:

В каждой версии этой функции строка userName может находиться в одном из различные форматы. Полный список приемлемых типы форматов, см. документацию ADS_NAME_TYPE_ENUM.

... из которых указан этот вид имени пользователя. Но это приводит к тому, что ValidateCredentials всегда возвращает true, независимо от того, какую комбинацию имени пользователя и пароля я передаю.

Соответствующий код:

bool authenticated = false;

// Various options tried for ContextOptions, [etc] inc. explicit username/password to bind to AD with -- no luck.
using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, domain, null, ContextOptions.Negotiate, null, null))
{
    log(pc.ConnectedServer + " => " + pc.UserName + " => " + pc.Name + " => " + pc.Container);
    using (var user = UserPrincipal.FindByIdentity(pc, IdentityType.SamAccountName, username))
    {
        if (user != null)
        {
            log(user.DistinguishedName + "; " + user.DisplayName);
            authenticated = pc.ValidateCredentials(username, password);
        } else {
            log("User not found");
            // Debug only -- is FindByIdentity() needed. This should always return 
            // false, but doesn't.
            authenticated = pc.ValidateCredentials(username, password);
        }
    }
}
return authenticated;

Любые предложения (разумные) приветствуются - я почесываю голову над этим, поскольку он просто противоречит ожиданиям.

Я должен добавить: это работает как я на моей машине, оба из которых являются членами основного домена. Однако я также попробовал запустить его в командной строке на моей машине в качестве пользователя поддомена (runas /user:subdomain\user cmd) с точно такими же результатами.

Ответ 1

Некоторое количество googling позже (не то, что я был в и из Google в течение всего дня, пытаясь найти это в любом случае), я нашел ответ.

Проще говоря, если учетная запись гостя включена в домене, ValidateCredentials вернет TRUE для неизвестного пользователя. Я только что проверил статус гостевого пользователя на сайте development.company.com, и, конечно же, учетная запись включена. Если у меня отключена гостевая учетная запись, ValidateCredentials корректно возвращает false.

Это довольно фундаментальный вопрос, но я не уверен, что увлекаюсь этим поведением... жаль, что он явно не упоминается в MSDN.

Ответ 2

Может ли это быть связано с this:

Метод ValidateCredentials привязывается к серверу, указанному в конструктор. Если параметры имени пользователя и пароля равны нулю, учетные данные, указанные в конструкторе, проверяются. Если нет учетные данные были указаны в конструкторе, а имя пользователя и параметры пароля равны нулю, этот метод проверяет значение по умолчанию учетные данные для текущего принципала.

Ответ 3

Я использовал флаг ContextOptions.SimpleBind с ValidateCredentials, это решило мою проблему..

Пример кода:

    using (var context = new PrincipalContext(ContextType.Domain, "DOMAIN", null))
    {
        bool loginResult = context.ValidateCredentials(username, password, ContextOptions.SimpleBind); // returns false for unknown user
    }