You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 07:54:22