В Active Directory (AD) пользователь может быть членом группы напрямую или косвенно через другую группу. Чтобы определить, является ли учетная запись пользователя косвенным членом группы AD, можно использовать следующий подход в Delphi:
Получениеhandle политики безопасности для компьютера, на котором выполняется приложение:
function GetPolicyHandle(const Computer: WideString=''): PLSA_HANDLE;
var
ObjectAttributes: LSA_OBJECT_ATTRIBUTES;
lusSystemName: LSA_UNICODE_STRING;
nts: NTSTATUS;
dwError: DWORD;
begin
ZeroMemory(@ObjectAttributes, SizeOf(ObjectAttributes));
RtlInitUnicodeString(@lusSystemName, PWideChar(Computer));
nts := LsaOpenPolicy(@lusSystemName, ObjectAttributes, POLICY_LOOKUP_NAMES,
Pointer(Result));
if nts <> STATUS_SUCCESS then
begin
dwError := LsaNtStatusToWinError(nts);
raise EOSError.Create(SysErrorMessage(dwError));
end;
end;
Получение membership группы пользователя с помощью атрибута "tokenGroups":
function GetGroupMembership(const AdsPath: WideString; var Groups: TStringList): Boolean;
const
Username: PChar = 'Administrator';
Password: PChar = 'password';
var
hr: HRESULT;
nts: NTSTATUS;
PolicyHandle: PLSA_HANDLE;
DirObject: IDirectoryObject;
Domains: PLSA_REFERENCED_DOMAIN_LIST;
Names: PLsaTranslatedNameArray;
SidArray: TSidArray;
Attributes: array of PChar;
AdValue: PAdsValueArray;
AdAttrInfo: PADS_ATTR_INFO;
dwNumAttributes: DWORD;
i: Integer;
s: WideString;
begin
Result := False;
Assert(Assigned(Groups));
// Get Lsa Policy Handle
PolicyHandle := GetPolicyHandle;
try
// Open AD object, note that I am using username, password because I am
// connecting from a machine that's not a domain member.
// I am also passing the ADS_SERVER_BIND flag because I am directly
// connecting to a specific Domain Controller
hr := ADsOpenObject(PWideChar(AdsPath), Username, Password,
ADS_SERVER_BIND or ADS_SECURE_AUTHENTICATION, IID_IDirectoryObject,
Pointer(DirObject));
if Failed(hr) then
Exit;
// Attribute array
SetLength(Attributes, 1);
s := 'tokenGroups';
Attributes[0] := @s[1];
hr := DirObject.GetObjectAttributes(@Attributes[0], Length(Attributes), AdAttrInfo, dwNumAttributes);
if Failed(hr) then
Exit;
// Setup an Array for the PSID's
SetLength(SidArray, AdAttrInfo^.dwNumValues);
AdValue := PAdsValueArray(AdAttrInfo^.pADsValues);
for i := 0 to AdAttrInfo^.dwNumValues-1 do
begin
// Copy Pointer to Array
Assert(AdValue^[i].OctetString.dwLength > 0);
SidArray[i] := PSid(AdValue^[i].OctetString.lpValue);
end;
nts := LsaLookupSids(PolicyHandle, Length(SidArray), @SidArray[0], Domains, PLSA_TRANSLATED_NAME(Names));
if nts >= STATUS_SUCCESS then
begin
for i := 0 to AdAttrInfo^.dwNumValues - 1 do
begin
SetLength(s, Names[i].Name.Length div SizeOf(WideChar));
CopyMemory(@s[1], Names[i].Name.Buffer, Names[i].Name.Length);
Groups.Add(s);
end;
// even if nts returns STATUS_NONE_MAPPED or STATUS_SOME_NOT_MAPPED we
// must Free the Mem!
LsaFreeMemory(Names);
LsaFreeMemory(Domains);
Result := True;
end;
FreeAdsMem(AdAttrInfo);
finally
// Close the Lsa Policy Handle
LsaClose(PolicyHandle);
end;
end;
Вызов функции GetGroupMembership с путем к объекту AD и списком групп в качестве параметров:
var
Groups: TStringList;
bRes: Boolean;
begin
Groups := TStringList.Create;
Groups.Duplicates := dupIgnore;
Groups.Sorted := True;
try
bRes := GetGroupMembership('LDAP://2003DC/CN=Administrator,CN=Users,DC=contoso,DC=com', Groups);
if bRes then
begin
for i := 0 to Groups.Count - 1 do
begin
Memo1.Lines.Add(Groups[i]);
end;
end;
Memo1.Lines.Add(Format('IsMemberOf Administrators: %s',
[BoolToStr(Groups.IndexOf('Administrators') <> -1, True)]));
finally
Groups.Free;
end;
end;
Пример выше демонстрирует, как определить, является ли учетная запись пользователя косвенным членом группы AD с помощью Delphi. Функция GetGroupMembership возвращает True, если пользователь является членом группы, и False в противном случае. Список групп, членом которых является пользователь,
Как определить, является ли учетная запись пользователя косвенным членом группы AD? В Active Directory (AD) пользователь может быть членом группы напрямую или косвенно через другую группу. Чтобы определить, является ли учетная запись пользователя косвенны
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.