如何在C++中通过LDAP查询当前用户的Active Directory组
使用LDAP格式操作Active Directory组的解决方案
以下是将原WinNT协议的AD组操作代码修改为LDAP协议的实现,支持指定LDAP服务器路径,同时实现查询当前登录用户所属组、检查用户是否在组内及添加用户到组的功能:
#include <windows.h> #include <iostream> #include <atlbase.h> #include <iads.h> #pragma comment(lib, "activeds.lib") #pragma comment(lib, "ole32.lib") HRESULT CheckAndManageUserInLDAPGroup() { HRESULT hr = S_OK; IADsGroup* pGroup = nullptr; IADsUser* pUser = nullptr; BSTR bstrGroupPath = nullptr; BSTR bstrUserPath = nullptr; VARIANT_BOOL isMember = VARIANT_FALSE; // 初始化COM环境 hr = CoInitialize(nullptr); if (FAILED(hr)) { std::cout << "COM初始化失败,错误码: 0x" << std::hex << hr << std::endl; goto Cleanup; } // 指定LDAP组路径:替换为你的AD服务器和组DN bstrGroupPath = SysAllocString(L"LDAP://10.20.214.74/CN=TestGroup,OU=Vimal,DC=test,DC=local"); if (!bstrGroupPath) { hr = E_OUTOFMEMORY; goto Cleanup; } // 绑定到LDAP组对象(如需域账号认证,可改用ADsOpenObject传入用户名密码) hr = ADsGetObject(bstrGroupPath, IID_IADsGroup, (void**)&pGroup); if (FAILED(hr)) { std::cout << "绑定到LDAP组失败,错误码: 0x" << std::hex << hr << std::endl; goto Cleanup; } // 获取组描述信息 BSTR bstrDesc = nullptr; hr = pGroup->get_Description(&bstrDesc); if (SUCCEEDED(hr) && bstrDesc) { std::wcout << L"组描述: " << bstrDesc << std::endl; SysFreeString(bstrDesc); } // 获取当前登录用户的LDAP路径 hr = ADsOpenObject(L"LDAP://rootDSE", nullptr, nullptr, ADS_SECURE_AUTHENTICATION, IID_IADs, (void**)&pUser); if (FAILED(hr)) { std::cout << "获取RootDSE失败,错误码: 0x" << std::hex << hr << std::endl; goto Cleanup; } BSTR bstrDefaultNamingContext = nullptr; hr = pUser->Get(CComBSTR("defaultNamingContext"), &bstrDefaultNamingContext); if (FAILED(hr) || !bstrDefaultNamingContext) { std::cout << "获取默认命名上下文失败,错误码: 0x" << std::hex << hr << std::endl; goto Cleanup; } // 获取当前用户名(格式:DOMAIN\Username) WCHAR szUserName[256] = {0}; DWORD dwSize = sizeof(szUserName) / sizeof(WCHAR); if (!GetUserNameW(szUserName, &dwSize)) { hr = HRESULT_FROM_WIN32(GetLastError()); std::cout << "获取当前用户名失败,错误码: 0x" << std::hex << hr << std::endl; goto Cleanup; } // 构造当前用户的LDAP路径 CComBSTR sbstrUserPath; sbstrUserPath.Format(L"LDAP://%s/%s", bstrDefaultNamingContext, szUserName); bstrUserPath = SysAllocString(sbstrUserPath); // 检查用户是否在组内 hr = pGroup->IsMember(bstrUserPath, &isMember); if (FAILED(hr)) { std::cout << "检查用户组成员身份失败,错误码: 0x" << std::hex << hr << std::endl; goto Cleanup; } if (isMember == VARIANT_TRUE) { std::wcout << L"当前用户已在组内。" << std::endl; } else { // 将用户添加到组 hr = pGroup->Add(bstrUserPath); if (SUCCEEDED(hr)) { std::wcout << L"用户已成功添加到组。" << std::endl; } else { std::cout << "添加用户到组失败,错误码: 0x" << std::hex << hr << std::endl; } } Cleanup: // 释放资源 if (pGroup) pGroup->Release(); if (pUser) pUser->Release(); if (bstrGroupPath) SysFreeString(bstrGroupPath); if (bstrUserPath) SysFreeString(bstrUserPath); if (bstrDefaultNamingContext) SysFreeString(bstrDefaultNamingContext); CoUninitialize(); return hr; } int main() { HRESULT hr = CheckAndManageUserInLDAPGroup(); return SUCCEEDED(hr) ? 0 : 1; }
关键说明:
- LDAP路径格式:必须使用完整的区分名(DN)格式,例如
LDAP://[服务器地址]/[组DN],组DN需根据你的AD结构调整(如CN=TestGroup,OU=Vimal,DC=test,DC=local)。 - 当前用户LDAP路径获取:通过
RootDSE获取默认命名上下文,结合当前用户名构造用户LDAP路径;也可使用ADsNameTranslate工具类将WinNT格式路径转换为LDAP格式。 - 认证方式:示例使用默认的安全认证(当前登录用户权限),若需要跨域或指定账号认证,需改用
ADsOpenObject并传入用户名、密码及认证标志(如ADS_SECURE_AUTHENTICATION)。 - COM初始化:必须调用
CoInitialize/CoUninitialize管理COM环境,否则无法使用ADSI接口。
内容的提问来源于stack exchange,提问作者Vimal A
相关产品推荐
相关产品推荐

