OPENLDAP API 编程简述

来源:互联网 发布:大数据人工智能的影响 编辑:程序博客网 时间:2024/05/17 16:16

http://www.lisdn.com/html/03/n-11703.html

一、 LDAP模型概览:
  1、 LDAP的数据存储在众多的Entry(条目)里;
  2、 LDAP中所有的Entry以树型结构组织在一起;
  3、 Entry由唯一的DN(Distinguished Name)标识和定位,DN就是树上到该Entry的路
      径标识;
  4、 Entry的数据以属性形式组织,每个属性可以拥有一个或多个值;
  5、 属性有各自的类型,一个Entry所能拥有的属性是由这个Entry的ObjectClass属性
      规定的;
  6、 每个Entry的Objectclass属性中必须包含top这个值,因为在top这个ObjectClass
      中定义了属性ObjectClass,Entry只有设置了该属性值才能拥有ObjectClass的属
      性(这是个递归定义,有点向pascal和c里的向前声明);
  7、 Entry能容纳的属性个数、属性值的类型、属性的名称(标识)都由该Entry的
      ObjectCalss规定(注意一个Entry的ObjectClass象它的其它属性一样是可以有多
      个值的)。以下是两个Entry的定义:
      以下两个Entry是同时由top,uidobject,person三个ObjectClass规范的Entry,注意
      它们的三个ObjectClass属性;由于这三个ObjectClass属性的规范,在增加、修改
      这两个Entry时必须要提供ObjectClass、uid、cn、sn的属性值。(关于Object参
      见下面的描述)
        dn: uid=10207, ou=People, o=VinSide, c=CN
        objectclass: top
        objectclass: uidobject
        objectclass: person
        uid: 10001
        cn: gang
        sn: liu
 
        dn: uid=10209, ou=People, o=VinSide, c=CN
        objectclass: top
        objectclass: uidobject
        objectclass: person
        uid: 10002
        cn: yuqing
        sn: tang
  8、 以下是ObjectClass(top,uidobject,person)的定义:
      其中在requires下的属性是设成该ObjectClass的Entry必须要设置的属性;
      其中在allow下的属性是设成该ObjectClass的Entry可以设置的属性,但不是必
      须的。
        objectclass top
                requires
                        objectClass
        objectclass uidobject
                requires
                        objectClass,
                        uid
        objectclass person
                requires
                        objectClass,
                        sn,
                        cn
                allows
                        description,
                        seeAlso,
                        telephoneNumber,
                        userPassword
  9、 Entry的DN描述这个Entry处于LDAP树型数据组织中的位置,如DN: uid=10207,
      ou=People, o=VinSide, c=CN的Entry就描述该Entry是DN: ou=People, o=VinSide,
      c=CN的Entry的子结点,故在添加DN: uid=10207, ou=People, o=VinSide, c=CN的
      Entry前DN: ou=People, o=VinSide, c=CN的Entry必须已经加入LDAP中;在删除
      结点时也存在同样的问题。
 
二、 使用LDAP API的步骤:
  1、 用ldap_open() API打开与LDAP服务器的连接,该API返回一个struct LDAP的
      指针,该指针将用于整个LDAP的操作过程直到结束;
  2、 用ldap_bind()族(如ldap_simple_bind、ldap_kerberos_bind等)API取得LDAP服
      务器的认证,只有获得认证(包括匿名认证)后才能对LDAP服务器提出请求;
  3、 执行具体的LDAP操作(如ldap_search()、ldap_add()、ldap_modify()、ldap_delet
()、
      ldap_first_entry()等);
  4、 关闭连接ldap_unbind();(这样整个操作过程就结束了)
 
三、 使用OpenLDAP API所需的头文件和连接库:
  1、 头文件(缺省安装在/usr/local/include):
       #include <lber.h>
       #include <ldap.h>
  2、 连接库(缺省安装在/usr/local/lib):
        libldap.a
        liblber.a
  3、 某些API需要额外的头文件,如<sys/time.h>,具体查看该API的man page(如man
      ldap_simple_bind_s )。
 
四、 LDAP API详述:
        说明:以下API中带"_s"后缀的API是同步API,即调用后会以阻塞方式运行;没有"
s"
        后缀的是异步API,调用后会立刻返回,然后在适当的时候用ldap_result()取回结
?
1、 ldap_open() 打开到LDAP服务器的连接:
              typedef struct ldap {
                      /* ... opaque parameters ... */
                      int     ld_deref;
                      int     ld_timelimit;
                      int     ld_sizelimit;
                      int     ld_errno;
                      char    *ld_matched;
                      char    *ld_error;
                      /* ... opaque parameters ... */
              } LDAP;
 
                LDAP *ldap_open( char *hostname, int portno );
        > hostname是LDAP服务器的地址,可以是IP或域名;
        > portno是LDAP服务器的端口号,缺省的端口是常数:LDAP_PORT;
        > 返回值:成功返回一个struct LDAP指针是一个连接句柄用于以后的操作,
          失败返回NULL。
2、 ldap_bind()族API获得访问目录的认证:
           int ldap_bind( LDAP *ld, char *dn, char *cred, int method );
 
           int ldap_bind_s( LDAP *ld, char *dn, char *cred, int method );
 
           int ldap_simple_bind( LDAP *ld, char *dn, char *passwd );
 
           int ldap_simple_bind_s( LDAP *ld, char *dn, char *passwd );
 
           int ldap_kerberos_bind( LDAP *ld, char *dn );
 
           int ldap_kerberos_bind_s( LDAP *ld, char *dn );
        > ld是连接句柄;
        > dn是要连接的Entry的DN。
          说明:该Entry会作为LDAP判断用ld句柄是否有权进行操作的依据(可
          以用帐号去理解,一般系统在配置时会设置一个rootdn可看作超级用户
          号)
        > passwd是对应dn的帐号密码
        > method是验证方法:LDAP_AUTH_SIMPLE,LDAP_AUTH_KRBV41,或
          LDAP_AUTH_KRBV42
        > 一般用简单的绑定就可以了:ldap_simple_bind_s、ldap_simple_bind
3、 ldap_unbind()关闭连接:
          int ldap_unbind( LDAP *ld );
        > ld是连接句柄
4、 ldap_search()族API查询LDAP目录:
           int ldap_search(
                   LDAP    *ld,
                   char    *base,
                   int     scope,
                   char    *filter,
                   char    *attrs[],
                   int     attrsonly
           );
           int ldap_search_s(
                   LDAP            *ld,
                   char            *base,
                   int             scope,
                   char            *filter,
                   char            *attrs[],
                   int             attrsonly,
                   LDAPMessage     **res
           );
           int ldap_search_st(
                   LDAP            *ld,
                   char            *base,
                   int             scope,
                   char            *filter,
                   char            *attrs[],
                   int             attrsonly,
                   struct timeval  *timeout,
                   LDAPMessage     **res
           );
        需要了解的结构:
                   struct timeval {
                           long    tv_sec;
                        long    tv_usec;
                   };
        > ld连接句柄
        > base搜索起始处那个Entry的DN
        > scope搜索范围:
                1. LDAP_SCOPE_BASE:只搜索该base Entry
                2. LDAP_SCOPE_ONELEVEL:搜索该base Entry的所有子Entry,但
                   只限于子Entry的那一层
                3. LDAP_SCOPE_SUBTREE:搜索该base Entry的整个子树(包括base
                   Entry)
        > filter是搜索过滤串,具体的描述在RFC1558,以下是简单的BNF描述:
               <filter> ::= '(' <filtercomp> ')'
               <filtercomp> ::= <and> | <or> | <not> | <simple>
               <and> ::= '&' <filterlist>
               <or> ::= '|' <filterlist>
               <not> ::= '!' <filter>
               <filterlist> ::= <filter> | <filter> <filterlist>
               <simple> ::= <attributetype> <filtertype> <attributevalue>
               <filtertype> ::= '=' | '~=' | '<=' | '>='
                说明:filtertype中的~=是专门用于近似匹配的
        > attrs是指出搜索将要返回哪些属性,它是以NULL标志结束的字符指针数
          组,如:attrs={"uid","sn","cn",NULL}。如果把attrs设成NULL表示传回所
          有的属性。
        > attrsonly是一个布尔值,0表示回传属性类型值和属性值,非0只传回属性
          类型。
        > timeout是专门用于ldap_search_st(),指出操作的超时时间。
        > res是同步API使用的,用于得到搜索结果。
          额外说明:(在ld这个连接句柄中有三个域影响搜索的进行)
        > ld_sizelimit:搜索结果中最大的Entry数
        > ld_timelimit:搜索消耗的时间限制(单位秒)
        > ld_deref:与别名有关的处理,具体看manual!
5、 目录查找结果分析API:
 i. 遍历结果目录项集(Entries Set)(ldap_first_entry、ldap_next_entry、
    ldap_count_entries):
           LDAPMesage *ldap_first_entry( LDAP *ld, LDAPMessage *res );
 
           LDAPMesage *ldap_next_entry( LDAP *ld, LDAPMessage *entry );
 
           int ldap_count_entries( LDAP *ld, LDAPMessage *res );
        > ld连接句柄
        > res搜索结果,从ldap_search()族函数或ldap_result()返回的。
        > entry是ldap_next_entry API中使用的,它是上次调用ldap_first_entry、
          ldap_next_entry的返回值,用于遍历正个Entry结果集。
        > 如果没有更多的Entry在结果集中,这两个API返回NULL。
        > 遍历开始先调用一次ldap_first_entry取得首个entry,然后调用ldap_next_ent
y
          遍历剩下的entry。

原创粉丝点击