Вот как 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
. Примечание. Это решение будет работать только в том случае, если все домены задействованы в одном лесу.
Изменил вопрос, чтобы включить весь метод. Попробует предложение ContextOption. Спасибо. –
B-Rain, Ссылка ContextOption указала мне в правильном направлении. Закончился с использованием ContextOptions.Negotiate при моем вызове AD и ContextOptions.SimpleBind для проверки учетных данных. Simple Bind будет работать для меня, так как сайт будет защищен SSL. Спасибо за помощь. –
Упрощенный вопрос и ответ, потому что это помогло мне и в моей ситуации. В моем случае моя машина dev (где вход работает без контекста) находится в защищенной зоне в сети, но веб-сервер (где логин не работает без контекста) находится в DMZ. Я использовал ту же конфигурацию, что и @Billy Logan - переговоры по вызову AD и SimpleBind при вызове проверки. – arootbeer