【问题标题】:From a C++ application, how can I check if a specific user in Active Directory is part of a particular security group?如何从 C++ 应用程序检查 Active Directory 中的特定用户是否属于特定安全组?
【发布时间】:2022-01-19 19:25:24
【问题描述】:

我目前正在开发一个 C++ 应用程序,该应用程序需要针对我们域上的 Active Directory(我正在工作)对用户进行身份验证,然后还要检查该用户是否属于该 Active Directory 中的特定安全组.我一直在使用 WinLDAP 进行身份验证(https://docs.microsoft.com/en-us/previous-versions/windows/desktop/ldap/establishing-an-ldap-session),我没有遇到任何问题。问题是 API 中似乎没有任何东西可以检查用户属于哪些安全组(在我们的 Active Directory 中),或者检查他们是否是特定组的成员。

我在其他线程中找到了一些答案,但它们要么 (1) 是用 C# 编写的,要么 (2) 只告诉您如何检查 当前用户 的 Active Directory 组Windows机器,这不是我需要的。 PC 上的当前用户可能不是登录到我们的应用程序的同一个人,或者他们可能使用不同的帐户登录到他们的 PC,而不是他们用于针对 Active Directory 进行身份验证的帐户。我需要能够指定要为其检查安全组的用户。

该解决方案不需要使用 LDAP,但它确实需要在 C++ 和 Windows 中工作。我们的应用程序也使用 Qt,所以我当然愿意接受需要 Qt 的选项。我真的只是在寻找一种简单的方式来表达“用户 [X] 是否属于域 [Z] 上的 Active Directory 中的组 [Y]”。 或者,它可以作为 “列出用户 [X] 在域 [Z] 上的 Active Directory 中所属的所有组”。 任何一个都可以,只要我可以在 AD 中指定用户名,这意味着它没有t 只对当前的 Windows 用户帐户进行操作。任何帮助将不胜感激!

【问题讨论】:

    标签: c++ windows qt active-directory ldap


    【解决方案1】:

    您可以使用Active Directory Service Interfaces (ADSI) 来执行此操作。这里有一个使用 ADsGetObject 绑定到用户帐户的 C++ 示例:Binding With GetObject and ADsGetObject

    如果将IID_IADsUser指定为riid参数,则可以获取IADsUser对象,然后使用IADsUser::Groups获取用户所属的所有组。

    C# 示例仍然对您有所帮助,因为 System.DirectoryServices 命名空间实际上只是 ADSI 的包装。例如,这个 C#:

    var user = new DirectoryEntry("LDAP://CN=jeffsmith,DC=fabrikam,DC=com");
    

    在 C++ 中相当于这个:

    hr = ADsGetObject(L"LDAP://CN=jeffsmith,DC=fabrikam,DC=com", IID_IADsUser, (void**) &pUser);
    

    DirectoryEntry.Properties 等价于IADs::Get/IADs::GetEx

    DirectoryEntry.RefreshCache 等价于IADs::GetInfo/IADs::GetInfoEx

    DirectoryEntry.CommitChanges 等价于IADs::SetInfo

    【讨论】:

    • 我遇到了“ADsGetObject”函数预期的“ADs Path”问题。我已经尝试过LDAPWinNT 两个版本,但我都不断收到错误消息。例如:LDAP://CN=test_user,CN=users,DC=ourdomain,DC=com --> ERROR_NO_SUCH_DOMAIN LDAP://dc1.ourdomain.com/CN=test_user,CN=users,DC=ourdomain,DC=com ---> ERROR_DS_OPERATIONS_ERROR ,并且使用 WinNT:WinNT://ourdomain.com/test_user,user --> ER_ACCESS_DENIED
    • 如果您运行它的计算机没有加入同一个域或受信任的域,它可能不知道去哪里找到DC=ourdomain,DC=com,所以你必须告诉它在 LDAP 路径中包括域的 DNS 名称,看起来您通过在 LDAP://dc1.ourdomain.com/CN=test_user,CN=users,DC=ourdomain,DC=com 中指定 DC 来尝试。您可以尝试只使用域名,而不是特定的 DC:LDAP://ourdomain.com/CN=test_user,CN=users,DC=ourdomain,DC=com
    • 我试过了,我的电脑已经加入了这个域。我什至将其简化为“LDAP://ourdomain.com”或“LDAP://ourdomain”。我知道这是有效的,因为我没有收到“没有这样的域”或“服务器关闭”错误。我继续得到的 only 错误是 ERROR_DS_OPERATIONS_ERROR。我不认为这是因为我有错误的域。其他东西似乎是错误的,但我无法弄清楚我错过了什么。这些是我目前仅有的几行:HRESULT hr; IADs* pObject; CoInitialize(NULL); hr = ADsGetObject(L"LDAP://ourdomain.com", IID_IADs, (void**)&pObject);
    • 您是否能够使用 Active Directory 用户和计算机来浏览您的域?还是 ldp.exe?
    • 我设法让ADsOpenObject 工作而不是ADsGetObject。我将“riid”参数设置为“IID_IADsUser”,所以我有一个用户对象可以使用,它说它是成功的。但是,当我使用该对象执行接下来的两行时:IADsMembers* groups; pObjectUser->Groups(&groups); 我似乎无法弄清楚如何遍历组列表。 “IADsMembers”的所有功能似乎都不是我需要的。 “IADsMembers”是错误的指针类型吗?如果没有,我应该如何遍历返回的组指针以查看组?
    猜你喜欢
    • 2023-02-23
    • 1970-01-01
    • 1970-01-01
    • 2011-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-11
    相关资源
    最近更新 更多