Подтвердить что ты не робот

PrincipalContext.ValidateCredentials всегда возвращает FALSE

У меня есть приложение 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;
}

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

4b9b3361

Ответ 1

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

Ответ 2

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

Проблема заключается в том, что формат NT4 (AKA "legacy", AKA "down-level name" ) (DOMAIN\UserName, вернее, NetBiosName\SamAccountName) не работает с Negotiate. Но он работает с SimpleBind.

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

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

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

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

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

1) Если все происходит в одном домене, вы можете вызвать ValidateCredentials только с именем пользователя (имя учетной записи SAM), оставив часть "DOMAIN \". Затем он будет работать правильно в первый раз с Negotiate.

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

Ответ 3

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