在Linux上使用C++对Active Directory进行身份验证

kis*_*tic 5 c++ linux kerberos active-directory

我很惊讶那里的例子很少.我基本上需要针对Active Directory进行用户/通过身份验证.我能够初始化到活动目录的连接,但它总是给我一个"无效的凭据"错误.我想知道我是不是错了.这是我第一次使用LDAP.就此而言,我对另一个(也许有很多文件记录)解决方案持开放态度.

#include <iostream>
#include <stdio.h>

#define LDAP_SERVER "ldap://hq.mydomain.local/"

#include <ldap.h>

int main( int argc, char** argv )
{
    LDAP    *ld;
    int     version( LDAP_VERSION3 );
    int     rc;
    char    bind_dn[100];
    berval  creds;
    berval* serverCreds;

    if( ldap_initialize( &ld, LDAP_SERVER ) ) {
        std::cerr << "Error initializing ldap..." << std::endl;
        return 1;
    }

    ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version );

    creds.bv_val = "password";
    creds.bv_len = strlen("password");

    rc = ldap_sasl_bind_s( ld, "sAMAccountName=MYDOMAIN\\UserName,dc=mydomain,dc=local", "GSSAPI", &creds, NULL, NULL, &serverCreds );

    if ( rc != LDAP_SUCCESS ) {
        std::cerr << "ERROR: " << ldap_err2string( rc ) << std::endl; 
        return 1;
    } else {
        std::cout << "Success." << std::endl;
    }

    return 0;

}
Run Code Online (Sandbox Code Playgroud)

编辑:

我想确保服务器端的一切正常,所以使用ldapsearch进行了一些测试.它起初没有用,但我终于得到了它(无论如何都是ldapsearch).

ldapsearch -D first.last@mydomain.local -H "ldap://hq.mydomain.local:389" -b "ou=Development,ou=Domain Users,dc=mydomain,dc=local" -W "sAMAccountName=first.last"
Run Code Online (Sandbox Code Playgroud)

也许不是最好的方式.对于初学者,键是-D参数,并在结尾传递sAMAccountName.我不会有通用名称 - 只有Windows登录名和密码.如果密码通过,上面的命令将向用户显示他的信息.

警告(我认为)是ldap_sasl_bind_s()没有相当于设置-D(binddn)标志.看看这个问题/答案它看起来像ldap_interactive_bind_s()可能,但它涉及更多,因为我必须传回一个回调.

通过上面的例子,我设置了一个密码,但没有任何类型的binddn/username,是谁假设我正在尝试进行身份验证?

smr*_*mr5 2

sAMAccountName=MYDOMAIN\用户名,dc=mydomain,dc=local

此用户名格式不正确。您不需要sAMAccountName在用户名中指定,也不需要指定,dc除非您使用Distinguished Name. 您的用户名选项很少。

  1. 专有名称

CN=Jeff Smith、OU=销售、DC=Fabrikam、DC=Com

  1. sAMac 计数名称

杰史密斯

  1. 以前版本的 Windows 中的用户路径

“法布里卡姆\杰夫史密斯”。

  1. 用户主体名称 (UPN)

jeffsmith@Fabrikam.com

话虽如此,我不确定用户名是否是您遇到的唯一问题。我没有在本地运行你的代码。

虽然这个答案可能不会直接回答你的问题,但由于我还没有在 Linux 机器上测试过这段代码,它可以给你一个想法或者让你走向正确的方向。如果此方法仅适用于 Windows,我不会感到惊讶。

根据MSDN,几乎没有什么methods可以用来验证用户身份。

ADsOpenObject函数使用显式用户名和密码凭据绑定到ADSI对象。

该方法接受以下参数:

HRESULT ADsOpenObject(
  _In_  LPCWSTR lpszPathName,
  _In_  LPCWSTR lpszUserName,
  _In_  LPCWSTR lpszPassword,
  _In_  DWORD   dwReserved,
  _In_  REFIID  riid,
  _Out_ VOID    **ppObject
);
Run Code Online (Sandbox Code Playgroud)

使用此方法,您可以通过指定username和绑定到 Active Directory 中的对象password

如果绑定成功,返回码为S_OK,否则您将收到不同的错误消息。

我不会C++每天编写程序。我通常在一个世界Active Directory中工作。但我编写的这个示例代码向您展示了如何调用方法来使用指定的凭据绑定到 ADSI 对象。就你而言,只需.Active Directory Lightweight ServicesC#ADsOpenObjectauthenticate

#include <iostream>
#include "activeds.h"

using namespace std;

int main(int argc, char* argv[])
{
   HRESULT hr;
   IADsContainer *pCont;
   IDispatch *pDisp = NULL;
   IADs *pUser;

   CoInitialize(NULL);

   hr = ADsOpenObject( L"LDAP://yourserver",
               L"username",
               L"password",
               ADS_FAST_BIND, //authentication option     
               IID_IADs,
               (void**) &pUser);


   if (SUCCEEDED(hr))
   {
      cout << "Successfully authenticated";
   }
   else
      cout << "Incorrect username or password";
   return hr;
}
Run Code Online (Sandbox Code Playgroud)

根据您的设置,您可能需要进行调整ADS_AUTHENTICATION_ENUM。我建议您安装SSL 证书并使用ADS_USE_SSL绑定。在 AD 中处理没有 SSL 的密码可能是一场噩梦。