php的LDAP扩展为php操作ldap提供了大量便捷的函数,通过调用这些函数,可以方便地使用php编程来进行LDAP的管理操作。

1、PHP配置LDAP扩展

PHP默认并没有启用LDAP扩展,为了启用LDAP扩展模块,对于Linux的操作系统,可以使用远程包管理工具安装php-ldap的相关rpm包,如果需要编译安装PHP,那就需要在编译之初使用参数—with-ldap来编译LDAP模块,同时,在php.ini中需要去掉启用ldap扩展配置前的注释才能使设置生效。对于windows系统,同样要在php.ini中启用php_ldap.dll扩展,才能确保模块真正生效。具体配置的方法这里不再详述。

配置成功以后,通过phpinfo函数打印的PHP模块信息中就能看到LDAP模块的信息,如图。

PHP官方提供的说明手册中对该模块提供的函数有详细的说明,具体参考http://php.net/manual/zh/book.ldap.php,现就项目中具体用到函数进行粗略总结,如果需要了解更为详细的说明,强烈推荐通过阅读php的官方手册来获取。

2、PHP连接LDAP服务器

与PHP和关系型数据库建立连接的过程类似,PHP连接LDAP服务器通常也是经过连接、认证(绑定管理员)、操作、关闭的过程。

PHP与LDAP建立连接主要用到的函数有:

(1)、ldap_connect( $hostname, $port ):与指定的LDAP主机建立连接

  • $hostname:表示主机名(IP);
  • $port:表示连接的端口号,由于LDAP默认使用的端口号是389,因此,如果省略此参数,表示默认连接指定服务器的389端口;
$host="ldap.messikiller.cn";
$port="389";
$link=ldap_connect( $hostname, $port ) or die( "Can’t connect to ldap server!" );

(2)、ldap_get_option( $link, $option ):获取已经建立连接的配置信息;

ldap_set_option( $link, $option, $value ):为建立的连接配置相关信息

  • $link:之前已经与LDAP建立的连接资源;
  • $option:LDAP配置项名称,具体的配置项可以参考PHP官方说明,这里主要说明一下LDAP_OPT_PROTOCOL_VERSION选项,这个选项主要是指定了连接中LDAP的版本,LDAP当前存在LDAPv2和LDAPv3两种版本,PHP默认的连接版本是LDAPv2,如果需要指定建立LDAPv3的连接,则需要使用函数ldap_set_option进行配置;

注意:由于一些PHP操作LDAP高级函数只能使用在LDAPv3中,因此一定要指定连接版本为LDAPv3才能使用这些高级函数

  • $value:配置项的取值,可以是布尔值或者整数。
ldap_set_option( $link, LDAP_OPT_PROTOCOL_VERSION, 3 ); //指定LDAP连接版本为LDAPv3

(3)、ldap_bind( $link, $manager, $password ):为建立的连接绑定管理员账号

  • $link:之前已经与LDAP建立的连接资源;
  • $manager:管理员dn名称;
  • $password:管理员认证密码;
$manager="cn=manager,dc=messikiller,dc=cn";
$password="123456";
ldap_bind( $manager, $password ) or die( "Can’t bind manager to connection!" );

(3)、ldap_unbind( $link ) / ldap_close( $link ):关闭已经建立的LDAP连接,ldap_unbin()ldap_close()在操作上没有区别,相互为别名关系。

ldap_close( $link ); //关闭LDAP连接

3、PHP获取LDAP数据

PHP与LDAP建立的可用的连接之后,就可以在连接的基础上进行查询操作来获取LDAP数据库中的信息。

(1)、ldap_search( $link, $base_dn, $filter ):指定的过滤条件下,搜索base_dn及其子树的全部记录,并返回搜索结果为结果集。

  • $link:之前已经建立的LDAP连接资源;
  • $base_dn:要搜索的的根dn名称,通常是整个LDAP域的根dn,如"dc=messikiller,dc=cn";
  • $filter:搜索的过滤条件,支持"*"通配符,具体的用法可以参考PHP官方手册。
//搜索dc=messikiller,dc=cn及其子树中givenName值以messi开头的条目
$results=ldap_search( $link, "dc=messikiller,dc=cn", "givenName=messi*" ); 

(2)、ldap_get_entries( $link, $result ):读取搜索后获得的结果集中具体的记录,并返回结果到一个多维数组中。

  • $link:建立的LDAP连接;
  • $result:通过搜索获取到的结果集;

ldap_get_entries()函数返回的多维数组中存放了具体的条目信息,下面列出了多维数组中存放的具体信息:

  • array["count"]:结果集中获取到的记录条数;
  • array[n]["dn"]:结果集中第n+1项的dn值;
  • array[n]["count"]:结果集中第n+1项的全部属性总数;
  • array[n]["attr"]["count"]:结果集中第n+1项记录中"attr"属性所有取值的个数;
  • array[n]["attr"][m]:结果集中第n+1项记录中"attr"属性的第m+1个值;
  • array[n][m]:第n+1项中第m+1个位置的属性。
//获取搜索结果到数组
$entries=ldap_get_entries( $link, $results );
//确定搜索到的记录数目
$count=$entries["count"];
//循环输出所有搜索到的记录的givenname属性
for( $i=0; $i < $count; $i++ )
{
    echo "givenName:".$entries[$i]["givenName"][0]."<br />";
}
//关闭连接
ldap_close( $link );

(3)、ldap_read( $link, $base_dn, $filter ):通过过滤条件只搜索一个特定的记录项base_dn,并返回结果为结果集。

  • $link:已经建立的连接资源;
  • $base_dn:要搜索的dn名称;
  • $filter:本次搜索的过滤条件。

注意:与ldap_search()不同,ldap_read()函数只能搜索并读取一条特定的记录,并不去遍历并搜索base_dn的子树。

//获取搜索结果到数组
$entries=ldap_get_entries( $link, $results );
//确定搜索到的记录数目
$count=$entries["count"];
//输出搜索到的记录的givenname属性
echo "givenName:".$entries[0]["givenName"][0]."<br />"
//关闭连接
ldap_close( $link );

(4)、ldap_count_entries( $link, $result ):直接获取结果集中的全部记录总数,效果与ldap_get_entries()函数返回的$entries["count"]一样,举例略。

4、PHP操作LDAP数据(增加、删除、修改)

(1)、ldap_add( $link, $dn, $entry ):向ldap中添加具有$entry指定属性的新dn。添加成功返回true,否则返回false。

  • $link:已经建立的连接;
  • $dn:要新增的dn名称;
  • $entry:新dn具有的属性名称和具体的值,该变量为数组形式。
//新dn名称
$new_dn="uid=people,dc=messikiller,dc=cn";
//指定新dn的属性
$entry=array( "cn"=>"people", "mail"=>"messikiller@aliyun.com" );
//添加dn到LDAP
ldap_add( $link, $new_dn, $entry ) or die( "Can’t add new dn!" );
//关闭ldap连接
ldap_close( $link );

(2)、ldap_mod_replace( $link, $dn, $entry ) / ldap_modify( $link, $dn, $entry ):修改已经存在的dn项的特定属性的值,要修改的属性和修改后的值由数组$entry指定。修改成功返回true,否则返回false。ldap_mod_replace()ldap_modify()互为别名关系。

  • $link:已经建立的连接;
  • $dn:要修改的具体dn名称;
  • $entry:修改的属性的修改后的值,该变量为数组形式。
//要修改的dn
$dn="uid=people,dc=messikiller,dc=cn";
//要修改的属性和修改后的属性值
$entry=array( "cn"=>"new_people", "mail"=>"messikiller@163.com" );
//修改属性,否则报错
ldap_mod_replace( $link, $dn, $entry ) or die ("Can’t modify attrs!");

(3)、ldap_mod_add( $link, $dn, $entry ):向指定的dn添加新的属性,新的属性名和属性值由数组$entry指定。

$dn="uid=people,dc=messikiller,dc=cn";
$entry=array( "dispalyName"=>"person", "age"=>"25" );
ldap_mod_add( $link, $dn, $entry ) or die ("Can’t add attrs!");

(4)、ldap_rename( $link, $dn, $new_rdn, $new_parent, $is_delete_old_rdn ):复制指定的dn,并修改指定dn的rdn名称。

$link:已经建立的连接;

$dn:要进行复制和重命名的dn名称;

$new_rdn:重命名后的新rdn名称;

$new_parent:复制后新dn的父节点dn;

$is_delete_old_rdn:复制后是否删除旧dn,该变量为布尔值。

注意:ldap_rename()函数只能在LDAPv3版本下执行,因此$link必须指定为LDAPv3版本。由于该函数在今后ldap结构迁移的项目中还会多次用到,这里不再举例。

(5)、ldap_mod_del( $link, $dn, $entry ):删除指定dn中的指定的属性,要删除的属性由数组$entry指定。

$link:已经建立的连接;

$dn:指定的dn;

$entry:定义要删除的具体属性,该变量为数组。

//要删除属性的dn
$dn="uid=people,dc=messikiller,dc=cn";
//要删除的属性名称
$entry=array( "dispalyName", "age" );
//删除指定的属性,负责报错
ldap_mod_del( $link, $dn, $entry ) or die ("Can’t delete attrs!");

(6)、ldap_delete( $link, $dn ):删除指定的dn实体。

//要删除的dn
$dn="uid=people,dc=messikiller,dc=cn";
//删除dn,否则报错
ldap_delete ( $link, $dn ) or die ("Can’t delete the dn!");

使用以上介绍的函数,基本可以实现通过PHP脚本来完成LDAP的增删改查,二次封装成具体需要的函数后,就能使用PHP完成一些较为复杂的LDAP操作,今后PHP脚本的编写基本都是建立在这些函数的基础之上。