Ответ 1
Я не вижу, где вы инициализируете переменную "pwd" Возможно, вы должны использовать ContextOption в этом методе, чтобы точно указать требуемое поведение. Извините за слишком широкий ответ, но в вашем вопросе нет подробностей.
У меня есть приложение 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;
}
Кто-нибудь знает, почему это происходит?
Я не вижу, где вы инициализируете переменную "pwd" Возможно, вы должны использовать ContextOption в этом методе, чтобы точно указать требуемое поведение. Извините за слишком широкий ответ, но в вашем вопросе нет подробностей.
Здесь работает 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
. Примечание. Это решение будет работать только в том случае, если все домены участвуют в одном и том же лесу.
Кажется, вы проверяете пользователя с помощью формата domain\userName. Вы можете проанализировать имя домена из userName и использовать ValidateCredential.