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_init(
UNICODE PTCHAR HostName,
ULONG PortNumber
);
如果函数执行成功,将返回一个指向 LDAP 数据结构的指针形式的会话句柄。否则,返回 NULL,可使用 LdapGetLastError 函数检索错误代码。
ULONG ldap_set_option(
LDAP* ld,
int option,
void* invalue
);
如果函数执行成功,返回值为 LDAP_SUCCESS。否则,返回错误代码。有关可能的返回值列表,请参阅 LDAP_RETCODE 枚举。
调用此函数以访问表示 LDAP 会话的 LDAP 结构,不要尝试直接修改 LDAP 数据结构。
要启用签名/密封,必须在调用 ldap_bind_s 之前打开以下选项之一:
#define LDAP_OPT_SIGN 0x95
#define LDAP_OPT_ENCRYPT 0x96
要关闭签名/密封,必须通过调用连接句柄上的 ldap_unbind 函数来关闭连接。
ULONG ldap_connect(
LDAP* ld,
PLDAP_TIMEVAL* timeout
);
如果函数执行成功,返回值为 LDAP_SUCCESS。否则,返回错误代码。有关可能的返回值列表,请参阅 LDAP_RETCODE 枚举。
通常客户端不调用此函数来建立与服务器的连接。如果连接不存在,其他函数将在内部进行调用。但是,有时可能需要在连接块上指定其他选项。例如,客户端可以调用 ldap_init 来初始化会话,然后调用 ldap_set_option 在连接块上设置超时。客户端然后调用 ldap_connect 以指定的超时连接到服务器。
ULONG ldap_bind_s(
LDAP* ld,
UNICODE PTCHAR dn,
UNICODE PTCHAR cred,
ULONG 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;
}