PrincipalContext.ValidateCredentials всегда возвращает FALSE - PullRequest
15 голосов
/ 02 марта 2010

У меня есть приложение MVC, которое должно войти в систему и проверить пользователя по Active Directory. Я использую метод PrincipalContext.ValidateCredentials, но всегда получаю аутентификацию false.

Подключение к серверу в порядке. Кажется, проблема возникает в ValidateCredentials.

Вот мой код:

public static bool IsAuthenticated(string domain, string username, string pwd) {
    bool IsAuthenticated = false;

    try {
        PrincipalContext insPrincipalContext = 
            new PrincipalContext(ContextType.Domain, domain, "DC=c1w,DC=com");

        username = "c1w\\" + username;

        IsAuthenticated = insPrincipalContext.ValidateCredentials(username, pwd);
    }
    catch (Exception ex)
    {
        // Rethrow this exception
        ExceptionPolicy.HandleException(ex, "Exception Policy");
    }

    return IsAuthenticated;
}

Кто-нибудь знает, почему это происходит?

Ответы [ 3 ]

14 голосов
/ 17 июля 2015

Вот как работает ValidateCredentials(string, string). Сначала он пытается пройти аутентификацию с помощью параметров контекста Negotiate, Signing и Sealing. Если это не удается, он пытается снова с SimpleBind и SecureSocketLayer.

Проблема заключается в том, что формат NT4 (AKA «устаревшее», AKA «имя нижнего уровня») (DOMAIN\UserName, или, точнее, NetBiosName\SamAccountName) не работает с Negotiate. Но он работает с SimpleBind.

Итак, что, вероятно, происходит при вызове двухпараметрического метода ValidateCredentials(), так это то, что он сначала терпит неудачу при использовании Negotiate, потому что ему не нравится формат NT4, а затем снова отказывает при использовании простого связывания.

Во время моего собственного тестирования я обнаружил, что причина его сбоя даже после отказа от простого связывания заключается в том, что он не только использует SimpleBind. Используется SimpleBind плюс SecureSocketLayer. Это означает, что все равно произойдет сбой, если сервер Active Directory неправильно настроен для использования SSL (общий сценарий для тестовых сред).

Как уже упоминалось в одном из комментариев, вы НИКОГДА, НИКОГДА не хотите использовать SimpleBind самостоятельно (без SecureSocketLayer), в противном случае ваши пароли передаются по сети в виде простого текста.

В реальных условиях я видел, что некоторые системы Active Directory вообще не позволяют использовать простые привязки, поэтому вы должны заставить его работать с Negotiate.

Я нашел 2 способа решения этой проблемы:

1) Если все происходит в одном и том же домене, вы сможете позвонить на ValidateCredentials только с именем пользователя (именем учетной записи SAM), оставив часть «ДОМЕН». Затем он будет правильно работать в первый раз с Negotiate.

2) Если доменная часть важна, поскольку может быть задействовано несколько доменов (т. Е. Domain1\UserA и Domain2\UserA - разные люди), то это становится немного сложнее. В этом случае я перевел NT4-имя (DOMAIN \ User) в формат «имя участника-пользователя» (например, LogonName@domain.com). Есть несколько разных способов сделать это. Возможно, проще всего использовать трехпараметрическую перегрузку UserPrincipal.FindByIdentity(), а затем получить значение свойства UserPrincipalName в результате. Другой способ - использовать DirectorySearcher и запрос LDAP://domain для свойства userPrincipalName пользователя с совпадающим значением sAMAccountName. Примечание. Это решение будет работать только в том случае, если все задействованные домены находятся в одном лесу.

9 голосов
/ 02 марта 2010

Я не вижу, где вы инициализируете переменную "pwd" Возможно, вам следует использовать ContextOption в этом методе, чтобы точно указать требуемое поведение. Извините за слишком широкий ответ, но в вашем вопросе не так много деталей

1 голос
/ 22 февраля 2012

Кажется, вы проверяете пользователя в формате domain \ userName. Возможно, вы захотите разобрать доменное имя по имени пользователя и использовать ValidateCredential.

...