windows下对LDAP实现增删改查(一)

LDAP提供标准的访问协议,采用的是ASN.1协议格式,不是很好理解,不过应用层方面提供c/c++的api,可以很方便的使用

windows下可以使用微软提供的一系列接口,MSDN文档介绍可查看

库的使用

打开MSDN的文档,随便打开一个接口,在接口介绍底部会说明使用的库及头文件

使用时需包含头文件winldap.h

链接库Wldap32.lib

#pragma comment(lib,"Wldap32.lib")

Qt的也可以在pro文件添加

LIBS += -lWldap32

连接ldap-server

ldap是基于TCP/IP协议,实现的是一种可靠连接,连接方式和套接字连接相似

按以下代码方式进行连接即可,简单身份验证流程是固定的

    PWSTR host = (PWSTR)L"192.168.33.167";  // 主机
    ULONG port = LDAP_PORT;  // 端口

    ULONG version = LDAP_VERSION3;  // 版本

    // 认证信息
    PWSTR dn = (PWSTR)L"cn=admin,c=cn";  // 管理员
    PWSTR cred = (PWSTR)L"xxxxx";  // 密码
    ULONG method = LDAP_AUTH_SIMPLE;  // 识别方法  

    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 服务器认证客户端,无身份验证访问dn和cred传NULL,只能进行查询访问,无法进行增删改
    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");

对比使用客户端工具连接

新增

相关要点看代码中的注释

 LDAPMod OClass, FName, cnName;
 //新增的条目dn
 PWSTR entry_dn = (PWSTR)L"cn=testCert,c=cn";

 const wchar_t *cn_value[] = {L"testCert", NULL};
 cnName.mod_op = LDAP_MOD_ADD;
 //属性类型
 cnName.mod_type = (PWSTR)L"cn";
 cnName.mod_values = (PWSTR *)cn_value;

 const wchar_t *oc_values[] = {L"inetOrgPerson", NULL};
 OClass.mod_op = LDAP_MOD_ADD;
 OClass.mod_type = (PWSTR)L"objectClass";
 //mod_values为wchar_t **类型,定义的是wchar_t *的数组,数组末尾需追加NULL
 OClass.mod_values = (PWSTR *)oc_values;

 const wchar_t *gn_values[] = {L"testCert", NULL};
 FName.mod_op = LDAP_MOD_ADD;
 FName.mod_type = (PWSTR)L"sn";
 FName.mod_values = (PWSTR *)gn_values;

 //该数组末尾也要追加NULL
 LDAPMod *NewEntry[10];

 NewEntry[0] = &cnName;
 NewEntry[1] = &FName;
 NewEntry[2] = &OClass;
 NewEntry[3] = NULL;
 rc = ldap_add_s(ld, entry_dn, NewEntry);
 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;
 }

当添加证书数据时,使用以上方式无法添加成功,调用方式会有所区别

    //Qt方式读取文件
    QByteArray fileData;
    QFile file("C:/Users/Songxd/Desktop/jj.cer");
    if(file.open(QIODevice::ReadOnly)) {
        fileData = file.readAll();
        file.close();
    }

    struct berval cert_berval;
    struct berval *cert_values[2];
    LDAPMod cert_attribute;
    cert_attribute.mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
    //证书的属性类型为userCertificate;binary
    cert_attribute.mod_type = (PWCHAR)L"userCertificate;binary";
    cert_berval.bv_len = fileData.size();
    cert_berval.bv_val = fileData.data();
    cert_values[0] = &cert_berval;
    cert_values[1] = NULL;
    cert_attribute.mod_bvalues = cert_values;

为什么证书需要用下面这种方式才能添加成功

我们到官方接口文档中找答案

https://docs.microsoft.com/en-us/windows/win32/api/winldap/ns-winldap-ldapmodw

先看ldapmod的结构

typedef struct ldapmodW {
     ULONG     mod_op;
     PWCHAR    mod_type;
     union {
        PWCHAR  *modv_strvals;
        struct berval   **modv_bvals;
    } mod_vals;
} LDAPModW, *PLDAPModW;

这两种用法的区别就是value值使用modv_strvalsmodv_bvals的区别

文档中说明

Pointer to an array of values, if any, to add, delete, or replace. If mop_op does not include the LDAP_MOD_BVALUES flag, the modv_strvals member is a pointer to an array of null-terminated strings. If mop_op includes LDAP_MOD_BVALUES, the modv_bvals member is a pointer to an array of berval pointers, which is useful for specifying binary values

如果mop_op不包含LDAP_MOD_BVALUES标志,则modv_strvals成员是指向空终止字符串数组的指针。如果mop_op包含LDAP_MOD_BVALUES,则modv_bvals成员是指向一个berval指针数组的指针,这对于指定二进制值很有用。

最后一句话说明了传二进制数据要用modv_bvals,证书数据使用userCertificate;binary,明确了使用二进制数据,即der的证书格式,尝试使用pem证书无法直接添加成功。

删除

删除就很简单了,传参要删的dn即可

    PWSTR entry_dn = (PWSTR)L"cn=testCert,c=cn";
    rc = ldap_delete_s(ld, entry_dn);
    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;
    }

修改

修改和新增是相通的

    LDAPMod Name, OClass, FName, LName, Title, Phone, Uid;
    PWSTR entry_dn = (PWSTR)L"cn=test22,c=cn";
    LDAPMod *NewEntry[3];

    const wchar_t *ho_values[] = {L"123456", NULL};
    //使用LDAP_MOD_REPLACE和LDAP_MOD_ADD都可以
    Uid.mod_op = LDAP_MOD_REPLACE;
    Uid.mod_type = (PWSTR)L"uid";
    Uid.mod_values = (PWSTR *)ho_values;

    NewEntry[0] = &Uid;
    NewEntry[1] = NULL;
    rc = ldap_modify_s(ld, entry_dn, NewEntry);
    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;
    }

结语

以上的ldap连接及增删改的内容,查询功能将在下一篇再进行介绍,毕竟查询是ldap的主打功能

 

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值