Active Directory - проверьте имя пользователя / пароль

Я использую следующий код в Windows Vista Ultimate SP1, чтобы запросить наш сервер Active Directory для проверки имени пользователя и пароля пользователя в домене.

public Object IsAuthenticated()
{
    String domainAndUsername = strDomain + "\\" + strUser;
    DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, strPass);
    SearchResult result;
    try
    {
        //Bind to the native AdsObject to force authentication.         

        DirectorySearcher search = new DirectorySearcher(entry) { Filter = ("(SAMAccountName=" + strUser + ")") };

        search.PropertiesToLoad.Add("givenName"); // First Name                
        search.PropertiesToLoad.Add("sn"); // Last Name
        search.PropertiesToLoad.Add("cn"); // Last Name

        result = search.FindOne();

        if (null == result)
        {
            return null;
        }

        //Update the new path to the user in the directory.
        _path = result.Path;
        _filterAttribute = (String)result.Properties["cn"][0];
    }
    catch (Exception ex)
    {
        return new Exception("Error authenticating user. " + ex.Message);
    }
    return user;
}

цель использует .NET 3.5 и скомпилирована по стандарту VS 2008

Я вошел в систему под учетной записью домена, которая является администратором домена, на котором запущено приложение.

Код отлично работает в Windows XP; но я получаю следующее исключение при запуске в Vista:

System.DirectoryServices.DirectoryServicesCOMException (0x8007052E): Logon failure: unknown user name or bad password.

   at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
   at System.DirectoryServices.DirectoryEntry.Bind()
   at System.DirectoryServices.DirectoryEntry.get_AdsObject()
   at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne)
   at System.DirectoryServices.DirectorySearcher.FindOne()
   at Chain_Of_Custody.Classes.Authentication.LdapAuthentication.IsAuthenticated()
   at System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)
   at System.DirectoryServices.DirectoryEntry.Bind()
   at System.DirectoryServices.DirectoryEntry.get_AdsObject()
   at System.DirectoryServices.DirectorySearcher.FindAll(Boolean findMoreThanOne)
   at System.DirectoryServices.DirectorySearcher.FindOne()
   at Chain_Of_Custody.Classes.Authentication.LdapAuthentication.IsAuthenticated()

Я пробовал изменить типы аутентификации, я не уверен, что происходит.


См. также: Проверить имя пользователя и пароль в Active Directory?


person Michael G    schedule 30.12.2008    source источник
comment
Это действительно точный дубликат? Этот человек получает сообщение об исключении, не спрашивая, как это сделать ...   -  person hugoware    schedule 30.12.2008
comment
Поскольку вы используете .NET 3.5, вы можете использовать System.DirectoryServices.AccountManagement. Я не использую Vista на работе, но, поскольку она предназначена для 3.5, она может быть более совместима с Vista ...   -  person hugoware    schedule 30.12.2008
comment
Я бы не назвал это обманом ....   -  person cgreeno    schedule 30.12.2008
comment
Я так или иначе понял это.Если вы переходите в домен с именем пользователя на Vista, он не работает как domain \ user, поэтому просто проход пользователя вместо этого, похоже, работает нормально - за исключением того, что вы должны быть в том же домене   -  person Michael G    schedule 30.12.2008


Ответы (4)


Если вы используете .net 3.5, используйте этот код.

Чтобы аутентифицировать пользователя:

PrincipalContext adContext = new PrincipalContext(ContextType.Domain);

using (adContext)
{
     return adContext.ValidateCredentials(UserName, Password);
}

Если вам нужно найти пользователя для чтения / записи атрибутов объекта, сделайте следующее:

PrincipalContext context = new PrincipalContext(ContextType.Domain);
UserPrincipal foundUser = 
    UserPrincipal.FindByIdentity(context, "jdoe");

Здесь используется пространство имен System.DirectoryServices.AccountManagement, поэтому вам нужно добавить его в операторы using.

Если вам нужно преобразовать объект UserPrincipal в объект DirectoryEntry для работы с устаревшим кодом, вы можете сделать это:

DirectoryEntry userDE = (DirectoryEntry)foundUser.GetUnderlyingObject();
person Steve Evans    schedule 01.01.2009
comment
Привет, @steve, вы имеете в виду, что нам не нужно указывать доменное имя при определении основного контекста? Тогда как он узнает, по какому домену следует проверять? Кроме того, не могли бы вы указать мне на его документацию, я не могу ее найти. - person User16119012; 21.01.2021

Я обнаружил, что тот же код распространяется в Интернете на нескольких веб-сайтах, и у меня это не сработало. Стив Эванс, вероятно, прав в том, что если вы используете .NET 3.5, вам не следует использовать этот код. Но если вы все еще используете .NET 2.0, вы можете попробовать это для аутентификации в своих службах AD:

DirectoryEntry entry = new DirectoryEntry("LDAP://" + domain, 
   userName, password, 
   AuthenticationTypes.Secure | AuthenticationTypes.SecureSocketsLayer);
object nativeObject = entry.NativeObject;

Первая строка создает объект DirectoryEntry с использованием домена, имени пользователя и пароля. Он также устанавливает AuthenticationTypes. Обратите внимание, как я устанавливаю и безопасную (Kerberos) аутентификацию, и SSL, используя оператор «Побитовое ИЛИ» ('|') между двумя параметрами.

Вторая строка вынуждает NativeObject из "entry" связываться со службами AD, используя информацию из первой строки.

Если возникает исключение, значит учетные данные (или настройки) неверны. Если нет исключения, вы аутентифицированы. Сообщение об исключении обычно указывает, что пошло не так.

Этот код очень похож на тот, который у вас уже есть, но домен используется там, где у вас есть «путь», а имя пользователя не совмещается с доменом. Не забудьте также правильно установить AuthenticationTypes. Это может сделать или нарушить возможность аутентификации.

person Pretzel    schedule 26.03.2010
comment
Вопрос касается .Net 3.5; не .Net 2.0. - person jww; 11.09.2014
comment
Это первый ответ, который я видел, который сочетает в себе флаги Secure и SecureSocketsLayer, и это единственный способ заставить его работать. Спасибо! - person EricRRichards; 28.10.2016

Я так или иначе понял это. Если вы передадите домен с именем пользователя на Vista, он не будет работать как «домен \ пользователь», поэтому просто передача «пользователь» вместо этого, похоже, работает нормально - за исключением того, что вы должны быть в том же домене

person Michael G    schedule 31.12.2008
comment
вы должны иметь возможность сменить домен, также перейдя в user @ domain - person Andrew Cox; 31.12.2008

Требует ли привязка к LDAP повышенных привилегий (UAC)? Вы можете попробовать запустить Visual Studio и / или приложение от имени администратора и посмотреть, поможет ли это. Если это проблема, вы всегда можете добавить манифест в приложение и настроить его так, чтобы он требовал повышения прав, таким образом он будет запрашивать, когда пользователь запускает его.

Не знаю, зачем нужны повышенные привилегии, но попробовать стоит.

person Steven Robbins    schedule 30.12.2008
comment
Запуск от имени администратора не помогает - person Michael G; 30.12.2008