Delphi 从不属于域的PC检查Active Directory中的用户名/密码
编辑:我根据Andrei Galattyn的评论和提示修改了代码,提示我不应依赖无效时为零的令牌,但它仍然不适用于不属于域的PCDelphi 从不属于域的PC检查Active Directory中的用户名/密码,delphi,ldap,delphi-2010,Delphi,Ldap,Delphi 2010,编辑:我根据Andrei Galattyn的评论和提示修改了代码,提示我不应依赖无效时为零的令牌,但它仍然不适用于不属于域的PC 我想验证用户输入的用户名/密码组合是否在LDAP服务器中有效 目前我使用以下代码: function CheckWinUserAccount(Username, Password, Domain : string) : boolean; var token: THandle; begin result:=False; if LogonUser(
我想验证用户输入的用户名/密码组合是否在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域一部分的PC上执行,而不是在仅将LDAP PC用作DNS但不属于该域一部分的PC上执行,则它可以完美地工作
我的数据:
- 域名:graz.local
- 用户名:LDTest
LDTest
、作为graz\LDTest
和作为graz.local\LDTest
我还尝试将域指定为graz
,graz.local
,ldap://graz.local
这些都不管用。有什么想法吗
顺便说一句:我不确定这是否可行(从非域PC访问域服务器),但使用LDAP管理员(Softerra)这是可行的。正如Andrei Galatyn所指出的,使用LOGON32\u登录\u网络而不是
LOGON32\u LOGON\u调用“LogonUser”时进行交互。用户名
不应包括域名,域名可以是
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.
{$APPTYPE控制台}
使用
SysUtils,
窗户,
JwaWinLDAP,
jcdce;
变量
sUsername、sDomain、sPassword、sDC:字符串;
LDAP:PLDAP;
SWAI:SEC_WINNT_AUTH_IDENTITY;
开始
如果(参数4),则
开始
WriteLn('WinLdapTest[username][domain][password][domain controller]”);
暂停(1);
结束;{if}
sUsername:=ParamStr(1);
sDomain:=ParamStr(2);
sPassword:=ParamStr(3);
sDC:=ParamStr(4);
LDAP:=LDAP_openW(PChar(sDC),LDAP_端口);
如果(已分配(LDAP)),则
尝试
SWAI.User:=PChar(sUserName);
SWAI.UserLength:=长度(sUserName);
SWAI.Domain:=PChar(sDomain);
SWAI.DomainLength:=长度(sDomain);
SWAI.Password:=PChar(sPassword);
SWAI.PasswordLength:=长度(sPassword);
SWAI.Flags:=SEC_WINNT_AUTH_IDENTITY_UNICODE;
如果(ldap、PChar(sDC)、PChar(@SWAI),
LDAP_AUTH_NTLM)=LDAP_成功)然后
WriteLN(''ldap_bind“success')
else WriteLN(''ldap_bind“failure');
最后
ldap_unbind(ldap);
结束{try/finally}
else WriteLn(“'ldap_open”失败”);
结束。
代码使用,并假设您使用的是Delphi 2009或更高版本(Unicode字符串)。要自动检索您可以调用的DC名称。如Andrei Galattyn所述,请使用LOGON32\u LOGON\u网络,而不是
LOGON32\u LOGON\u调用“LogonUser”时进行交互。用户名
不应包括域名,域名可以是
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.
{$APPTYPE控制台}
使用
SysUtils,
窗户,
JwaWinLDAP,
jcdce;
变量
sUsername、sDomain、sPassword、sDC:字符串;
LDAP:PLDAP;
SWAI:SEC_WINNT_AUTH_IDENTITY;
开始
如果(参数4),则
开始
WriteLn('WinLdapTest[username][domain][password][domain controller]”);
暂停(1);
结束;{if}
sUsername:=ParamStr(1);
sDomain:=ParamStr(2);
sPassword:=ParamStr(3);
sDC:=ParamStr(4);
LDAP:=LDAP_openW(PChar(sDC),LDAP_端口);
如果(已分配(LDAP)),则
尝试
SWAI.User:=PChar(sUserName);
SWAI.UserLength:=长度(sUserName);
SWAI.Domain:=PChar(sDomain);
SWAI.DomainLength:=长度(sDomain);
SWAI.Password:=PChar(sPassword);
SWAI.PasswordLength:=长度(sPassword);
SWAI.Flags:=SEC_WINNT_AUTH_IDENTITY_UNICODE;
如果(ldap、PChar(sDC)、PChar(@SWAI),
LDAP_AUTH_NTLM)=LDAP_成功)然后
WriteLN(''ldap_bind“success')
else WriteLN(''ldap_bind“failure');
最后
ldap_unbind(ldap);
结束{try/finally}
else WriteLn(“'ldap_open”失败”);
结束。
代码使用,并假设您使用的是Delphi 2009或更高版本(Unicode字符串)。自动检索您可以调用的DC名称。AFAIK,当结合域+用户名时,它应该是反斜杠(`\`),而不是正斜杠(`/`)。尝试登录32\u LOGON\u NETWORK,而不是LOGON32\u LOGON\u INTERACTIVE(这似乎是此类任务的错误参数)。感谢您的评论,我在帖子中提到了这一点,但是代码仍然只在属于域的计算机上工作。好吧,当结合域+用户名时,它应该是反斜杠(`\``),而不是正斜杠(`/`)。尝试登录32\u LOGON\u NETWORK而不是LOGON32\u LOGON\u INTERACTIVE(这似乎是此类任务的错误参数)。感谢您的评论,我在文章中提到了这一点,但代码仍然只在属于域的计算机上工作。非常感谢您的代码,这是一种可能的方式,因为LogonUser不适用于我,即使我使用LOGON32\u LOGON\u网络。。DsGetDcName方法似乎需要大量参数。我尝试了NetGetAnyDCName(nil,domainname,buf),它返回“\\LDAPSERVER”。看来我需要去掉反斜杠了。将DC=“LDAPSERVER”添加到您的方法可以工作,但完全忽略sDomain。)这不重要