Вот как работает 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
. Примечание. Это решение будет работать только в том случае, если все задействованные домены находятся в одном лесу.