Проверьте имя пользователя / пароль в Active Directory с ПК, который НЕ является частью домена

Изменить: Я изменил код в соответствии с комментарием Андрея Галатына и намекнул, что я не буду полагаться, что токен будет нулевым, если он недействителен, но он все еще не работает для ПК, которые не являются частью домена.


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

В настоящее время я использую этот код:

function CheckWinUserAccount(Username, Password, Domain : string) : boolean;
var token: THandle;
begin
     result:=False;
     if LogonUser( PChar(Username), PChar(Domain), PChar(Password),
                   LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, token) then
     begin
          CloseHandle(token);
          result:=True;
     end;
end;

Он отлично работает, если выполняется на ПК, который является частью домена LDAP, но не на ПК, который использует только компьютер LDAP в качестве DNS, но не является частью домена.

Мои данные:

  • Домен: graz.local
  • Имя пользователя: LDTest

Я попытался ввести имя пользователя как LDTest, как graz\LDTest и в качестве graz.local\LDTest,

Я также попытался указать домен как graz, graz.local, ldap://graz.local

Ничего из этого не сработало. Любая идея?

Кстати: я не был уверен, возможно ли это вообще (доступ к серверу домена с компьютера, не являющегося доменом), но с помощью администратора LDAP (от Softerra) это работает.

1 ответ

Как отметил Андрей Галатын, при вызове "LogonUser" используйте LOGON32_LOGON_NETWORK вместо LOGON32_LOGON_INTERACTIVE. Имя пользователя не должно включать имя домена, имя домена может быть либо именем домена NetBIOS ("graz"), либо именем домена DNS ("graz.local").

РЕДАКТИРОВАТЬ: Использование "LogonUser" работает, только если клиент уже установил соединение с доменом.

Вот код, который выполняет аутентификацию с использованием LDAP.

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Windows,
  JwaWinLDAP,
  JwaRpcDce;

var
    sUsername, sDomain, sPassword, sDC : String;
    LDAP : PLDAP;
    SWAI : SEC_WINNT_AUTH_IDENTITY;

begin
    if (ParamCount <> 4) then
    begin
        WriteLn ('WinLdapTest [username] [domain] [password] [domain controller]');
        Halt (1);
    end; { if }

    sUsername := ParamStr (1);
    sDomain := ParamStr (2);
    sPassword := ParamStr (3);
    sDC := ParamStr (4);

    LDAP := ldap_openW (PChar (sDC), LDAP_PORT);

    if (Assigned (LDAP)) then
        try
            SWAI.User := PChar (sUserName);
            SWAI.UserLength := Length (sUserName);
            SWAI.Domain := PChar (sDomain);
            SWAI.DomainLength := Length (sDomain);
            SWAI.Password := PChar (sPassword);
            SWAI.PasswordLength := Length (sPassword);
            SWAI.Flags := SEC_WINNT_AUTH_IDENTITY_UNICODE;

            if (ldap_bind_sW (LDAP, PChar (sDC), PChar (@SWAI),
                              LDAP_AUTH_NTLM) = LDAP_SUCCESS) then
                WriteLN ('"ldap_bind" success')
            else WriteLN ('"ldap_bind" failure');

        finally
            ldap_unbind (LDAP);
        end { try / finally }
    else WriteLn ('"ldap_open" failed');
end.

Код использует библиотеку JEDI API и предполагает, что вы используете Delphi 2009 или более позднюю версию (строки Unicode). Чтобы автоматически получить имя DC, вы можете вызвать DsGetDcName.

Другие вопросы по тегам