12

У меня есть приложение MVC, которому необходимо войти в систему и проверить пользователя в Active Directory. Я использую метод PrincipalContext.ValidateCredentials, но всегда получаю аутентификацию false.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; 
} 

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

ответ

7

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

+0

Изменил вопрос, чтобы включить весь метод. Попробует предложение ContextOption. Спасибо. –

+5

B-Rain, Ссылка ContextOption указала мне в правильном направлении. Закончился с использованием ContextOptions.Negotiate при моем вызове AD и ContextOptions.SimpleBind для проверки учетных данных. Simple Bind будет работать для меня, так как сайт будет защищен SSL. Спасибо за помощь. –

+0

Упрощенный вопрос и ответ, потому что это помогло мне и в моей ситуации. В моем случае моя машина dev (где вход работает без контекста) находится в защищенной зоне в сети, но веб-сервер (где логин не работает без контекста) находится в DMZ. Я использовал ту же конфигурацию, что и @Billy Logan - переговоры по вызову AD и SimpleBind при вызове проверки. – arootbeer

1

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

12

Вот как 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 плюс SecureSocketLayer. Это означает, что он все равно будет терпеть неудачу, если сервер Active Directory не настроен правильно для использования SSL (общий сценарий для тестовых сред).

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

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

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

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

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

Смежные вопросы