LDAP 认证(Windows)

简述

LDAP(Lightweight Directory Access Protocol - 轻量级目录访问协议)是一种目录服务协议,运行在 TCP/IP 栈之上的一层。它提供了一种用于连接、搜索、和修改 Internet 目录的机制。

LDAP 目录服务基于 client-server 模型,LDAP 的功能是允许访问现有目录。

LDAP 的数据模型(数据和命名空间)类似于 X.500 OSI 目录服务,但资源要求较低。相关联的 LDAP API 简化了编写 Internet 目录服务应用程序的过程。

关于 LDAP 的操作,有 C/C++ 的支持,可参考 MSDN 中的 Lightweight Directory Access Protocol,也可使用 OpenLDAP

| 版权声明:一去、二三里,未经博主允许不得转载。

初始化 LDAP

LDAP* ldap_init(
  UNICODE PTCHAR HostName,
  ULONG PortNumber
);
  • HostName:表示要连接的 LDAP 服务器的主机 IP 地址。
  • PortNumber:表示要连接的 TCP 端口号。设置为 LDAP_PORT 则为默认端口 389,如果主机名包含端口号,将忽略此参数。

如果函数执行成功,将返回一个指向 LDAP 数据结构的指针形式的会话句柄。否则,返回 NULL,可使用 LdapGetLastError 函数检索错误代码。

设置连接块上的选项

ULONG ldap_set_option(
  LDAP* ld,
  int option,
  void* invalue
);
  • ld:会话句柄
  • option:设置的会话选项的名称
  • invalue:指向给定 option 值的指针。此参数的实际类型取决于 option 参数的设置,可以指定具有开或关设置的常量 LDAP_OPT_ON 和 LDAP_OPT_OFF 选项。

如果函数执行成功,返回值为 LDAP_SUCCESS。否则,返回错误代码。有关可能的返回值列表,请参阅 LDAP_RETCODE 枚举。

调用此函数以访问表示 LDAP 会话的 LDAP 结构,不要尝试直接修改 LDAP 数据结构。

要启用签名/密封,必须在调用 ldap_bind_s 之前打开以下选项之一:

#define LDAP_OPT_SIGN      0x95
#define LDAP_OPT_ENCRYPT   0x96

要关闭签名/密封,必须通过调用连接句柄上的 ldap_unbind 函数来关闭连接。

连接 LDAP 服务器

ULONG ldap_connect(
  LDAP* ld,
  PLDAP_TIMEVAL* timeout
);
  • ld:会话句柄
  • timeout:超时前尝试建立连接的秒数

如果函数执行成功,返回值为 LDAP_SUCCESS。否则,返回错误代码。有关可能的返回值列表,请参阅 LDAP_RETCODE 枚举。

通常客户端不调用此函数来建立与服务器的连接。如果连接不存在,其他函数将在内部进行调用。但是,有时可能需要在连接块上指定其他选项。例如,客户端可以调用 ldap_init 来初始化会话,然后调用 ldap_set_option 在连接块上设置超时。客户端然后调用 ldap_connect 以指定的超时连接到服务器。

向 LDAP 服务器认证客户端

ULONG ldap_bind_s(
  LDAP* ld,
  UNICODE PTCHAR dn,
  UNICODE PTCHAR cred,
  ULONG method
);
  • ld:会话句柄
  • dn:用于绑定的条目的可分辨名称
  • cred:要进行身份验证的凭据。可以使用此参数传递任意凭证,凭据的格式和内容取决于机制参数的设置。
  • method:指示要使用的认证方法。

如果函数执行成功,返回值为 LDAP_SUCCESS。否则,返回错误代码。有关可能的返回值列表,请参阅 LDAP_RETCODE 枚举。

基本使用

使用时依赖库 Wldap32.lib(Wldap32.dll),需要包含头文件 Winldap.h。

#include "stdafx.h"
#include "windows.h"
#include "winldap.h"
#include "stdio.h"

int _tmain(int argc, _TCHAR* argv[])
{
    PWSTR host = L"172.18.***.***";  // 主机
    ULONG port = LDAP_PORT;  // 端口

    ULONG version = LDAP_VERSION3;  // 版本

    // 认证信息
    PWSTR dn = L"uid=ldapuser1,ou=People,dc=cloud,dc=com";  // 唯一的识别名
    PWSTR cred = L"password";  // 识别证书
    ULONG method = LDAP_AUTH_SIMPLE;  // 识别方法

    // 搜索结果
    LDAPMessage *res = NULL;
    PWSTR base_dn = L"ou=People,dc=cloud,dc=com";
    PWSTR filter = L"(&(objectClass=person))";

    LDAP *ld = NULL;  // 连接的句柄
    ULONG rc = 0;  // 返回值

    // 初始化 LDAP
    ld = ldap_init(host, port);
    if (ld == NULL) {
        fprintf(stderr, "ldap_init failed");
        return -1;
    }
    printf("ldap_init success\n");

    // 设置协议版本为 3.0(默认 2.0)
    rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version);
    if (rc != LDAP_SUCCESS) {
        fprintf(stderr, "ldap_set_option: rc: %d\n", rc);
        return -1;
    }
    printf("ldap_set_option success\n");

    // 连接 LDAP 服务器
    rc = ldap_connect(ld, NULL);
    if (rc != LDAP_SUCCESS) {
        fprintf(stderr, "ldap_connect: rc: %d\n", rc);
        return -1;
    }
    printf("ldap_connect success\n");

    // 向 LDAP 服务器认证客户端
    rc = ldap_bind_s(ld, dn, cred, method);
    if (rc != LDAP_SUCCESS) {
        fprintf(stderr, "ldap_bind_s: rc: %d\n", rc);
        return -1;
    }
    printf("ldap_bind_s success\n");

    // 搜索结果
    PWCHAR attrs[6];
    attrs[0] = (WCHAR*)"cn";
    attrs[1] = (WCHAR*)"company";
    attrs[2] = (WCHAR*)"givenName";
    attrs[3] = (WCHAR*)"sn";
    attrs[4] = (WCHAR*)"memberOf";
    attrs[5] = NULL;

    rc = ldap_search_s(
        ld,                 // 会话句柄
        base_dn,            // 指向查询开始处对象的指针,可以作为数的顶端,或者某一个低的点
        LDAP_SCOPE_SUBTREE, // 范围
        filter,             // 过滤器
        attrs,              // 检索属性列表
        0,                  // 设置为 1,只返回属性的类型,通常设定为 0,返回属性类型和值
        &res);              // [输出]搜索结果

    if (rc != LDAP_SUCCESS) {
        fprintf(stderr, "ldap_search_s: rc: %d\n", rc);
        ldap_unbind_s(ld);
        if (res != NULL)
            ldap_msgfree(res);

        return -1;
    }
    printf("ldap_search_s success\n");

    // 获取返回的条目数
    ULONG count = ldap_count_entries(ld, res);
    printf("The number of entries is: %d\n", count);

    return 0;
}

更多参考

展开阅读全文
©️2020 CSDN 皮肤主题: 技术黑板 设计师: CSDN官方博客 返回首页
实付0元
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值