LDAP 的全称是“轻量级目录访问协议(Lightweight Directory Access Protocol)”,是一种简单的目录协议。所谓目录,是一种专门的数据库,可以用来服务于任何应用程序。在企业应用中使用 LDAP可以让企业范围内的所有应用程序LDAP 目录中获取信息,应用程序可以从网络上直接从 LDAP 目录获取信息,而不局限于操作系统与服务器的类型。这里主要介绍如何使用 PHP 来访问 LDAP。
LDAP目录中的信息是是按照树型结构组织,具体信息存储在条目(entry)的数据结构中。条目相当于关系数据库中表的记录;条目是具有区别名DN (Distinguished Name)的属性(Attribute),DN是用来引用条目的,DN相当于关系数据库表中的关键字(Primary Key)。
LDAP简称对应
1.o-organization
2.ou-organization unit
3.c- countryName
4.dc-domainComponent
5.sn-suer name
6.cn-common name
PHP中用于连接LDAP服务器的函数时ldap_connect,其语法格式如下所示。
ldap_connect([string hostname [, int port]])其中,hostname是LDAP服务器所在的主机地址,port是LDAP服务器的端口号。以下代码实现了对位于192.168.3.1地址的服务器连接。
<?PHP $ldap_host = "ldap:192.168.3.1";//LDAP服务器地址 $ldap_port = "389"; $ldap_conn = ldap_connect($ldap_host,$ldap_port) or die ("Can't connect to LDAP server");//建立与LDAP服务器连接 ?>
绑定 LDAP 服务器的含义是使用特定的用户名或密码来登陆 LDAP 服务器。PHP 中用于绑定 LDAP服务器的函数是 ldap_bind,其语法格式如下所示。
ldap_bind(ldap_conn[,string username [, string password]])其中ldap_conn是前面连接LDAP服务器时创建的连接对象,username是登陆LDAP服务器时使用的用户名,password是登陆时所用的密码。以下代码实现了对位于198.168.3.1地址的LDAP服务器的绑定。
<?php $ldap_host = "ldap:192.168.3.1";//LDAP服务器 $ldap_port = "386";//LDAP服务器端口号 $ldap_user = "";//设定服务器用户名 $ldap_pwd = "";//设定服务器密码 $ldap_conn = ladp_connect($ldap_host,$ladp_port) or die("Can't connect to the LDA server."); $ldap_bind($ldap_conn,$ldap_user,$ldap_pwd) or die("Can't bind to LDAP server."); ?>断开LDAP服务器
与LDAP服务器断开的过程与绑定LDAP服务器相反,PHP中用于绑定LDAP服务器的函数时ldap_unbind,其语法格式如下
ldap_unbind(ldap_conn)
其中,ldap_conn 是前面连接 LDAP 服务器时创建的连接对象。以下代码在绑定了对位于 192.168.3.1地址的 LDAP 服务器后与其断开连接。
<?PHP $ldap_host = "ldap://192.168.3.1"; $ldap_user = ""; $ldap_pwd = "";//设定服务器密码 $ldap_conn = ldap_connect($ldap_host, $ldap_port) or die("Can't connect to LDAP server"); ldap_bind($ldap_conn, $ldap_user, $ldap_pwd) or die("Can't bind to LDAP server."); ldap_unbind($ldap_conn) or die("Can't unbind from LDAP server."); ?>
查询LDAP目录使用ldap_search函数来实现,其语法格式如下所示。
ldap_search(ldap_conn,base_dn,conditions)其中,ldap_conn是前面连接LDAP服务器时创建的连接对象。base_dn是LDAP服务器的查询主键。conditions是用于LDAP目录查询所用的条件。该函数返回一个结果对象,该结果对象保存查询到的所有记录。对于这个结果对象,可以使用ldap_get_entries函数进行简单的读取,其语法格式如下所示。
ldap_get_entries(ldap_conn,result)其中,ldap_conn 是前面连接 LDAP 服务器时创建的连接对象,result 是前面查询 LDAP 目录时返回的对象。该函数返回一个数组,包含所有的结果记录。以下代码实现了对服务器上的内容进行查询。
<?php $ldap_host = "ldap://192.168.3.1";//LDAP 服务器地址 $ldap_port = "389";//LDAP 服务器端口号 $ldap_user = "";//设定服务器用户名 $ldap_pwd = "";//设定服务器密码 $ldap_conn = ldap_connect($ldap_host, $ldap_port) or die("Can't connect to LDAP server");//建立与 LDAP 服务器的连接 ldap_bind($ldap_conn, $ldap_user, $ldap_pwd) or die("Can't bind to LDAP server.");//与服务器绑定 $base_dn = "ou=company,o=depart";//定义要进行查询的目录主键 $filter_col = "mail";//定义用于查询的列 $filter_val = "[email protected]";//定义用于匹配的值 $result= ldap_search($ldap_conn, $base_dn, "($filter_col=$filter_val)"); $entry= ldap_get_entries($ldap_conn, $result);//获得查询结果 print_r($entry); ldap_unbind($ldap_conn) or die("Can't unbind from LDAP server."); //与服务器断开连接 ?>
运行结果如下所示。
Array ( [count] => 1 [0] => Array ( [objectclass] => Array ( [count] => 5 [0] => person [1] => organizationalPerson [2] => companyPerson [3] => departPerson [4] => top ) [0] => objectclass [ou] => Array ( [count] => 1 [0] => company ) [1] => ou [o] => Array ( [count] => 1 [0] => depart ) [2] => o [employeeserialnumber] => Array ( [count] => 1 [0] => 100001 ) [3] => employeeserialnumber [givenname] => Array ( [count] => 2 [0] => Peng Cheng [1] => Peng ) [4] => givenname [mail] => Array ( [count] => 1 [0] => [email protected] ) [5] => mail [count] => 6 [dn] => uid=672100001,c=cn,ou=company,o=depart ) )可以看出,访问LDAP服务器与查询数据库中的记录很相似。事实上,在实际应用中,LDAP服务器也与数据库服务器有着相似的作用。除了上面的用法外,ldap_search函数还支持通配符使用。例如,将前面的用于LDAP服务器查询的代码修改如下。
<?php $filter_val = "*@163.com";//定义用于匹配的值 $result= ldap_search($ldap_conn, $base_dn, "($filter_col=$filter_val)");//执行查询 ?>这里就会将所有包含以“@163.com”结尾的邮件地址的记录返回。
上面的例子完整的获得了LDAP服务器查询结果的信息,这样,根据数组中的值就可以进行其他操作了。除此之外,PHP还提供了专门用于获得查询结果值的方法。首先介绍一种与ldap_get_entries相似的函数--ldap_first_entry,函数仅获得结果对象中的第一条记录,其语法格式如下。
ldap_first_entry(ldap_conn, result)其中,ldap_conn 是前面连接 LDAP 服务器时创建的连接对象,result 是前面查询 LDAP 目录时返回的对象。获取结果中的值的函数为 ldap_get_values,该函数的语法格式如下所示。
ldap_get_values(ldap_conn, entry, column)其中,ldap_conn 是前面连接 LDAP 服务器时创建的连接对象,entry 是前面查询查询结果时返回的对象,column 是要返回的值所在的列的名称。该函数返回一个仅包含该列信息的数组。以下代码返回了前面数组的 givenname 列。
<?php $ldap_host = "ldap://192.168.3.1"; //LDAP 服务器地址 $ldap_port = "389"; //LDAP 服务器端口号 $ldap_user = ""; //设定服务器用户名 $ldap_pwd = ""; //设定服务器密码 $ldap_conn = ldap_connect($ldap_host, $ldap_port) or die("Can't connect to LDAP server");//建立与 LDAP 服务器的连接 ldap_bind($ldap_conn, $ldap_user, $ldap_pwd) or die("Can't bind to LDAP server.");//与服务器绑定 $base_dn = "ou=company,o=depart";//定义要进行查询的目录 $filter_col = "mail";//定义用于查询的列 $filter_val = "[email protected]";//定义用于匹配的值 $result= ldap_search($ldap_conn, $base_dn, "($filter_col=$filter_val)");//执行查询 $entry = ldap_first_entry($ldap_conn, $result);//获得第一个查询结果 $firstname = ldap_get_values($ldap_conn, $entry, "givenname");//获得查询结果中的值 print_r($firstname);//输出 ldap_unbind($ldap_conn) or die("Can't unbind from LDAP server.");//与服务器断开连接 ?>运行结果如下所示。
Array ( [0] => Peng Cheng [1] => Peng [count] => 2 )
计算查询结果中的记录数ldap_count_entries函数来实现,该函数的语法格式如下所示、
ldap_count_entries(ldap_conn, result)其中,ldap_conn是前面连接LDAP服务器时创建的连接对象 ,result 是前面查询 LDAP 目录时返回的对象。以下代码计算出了查询结果中的记录数。
<?php $ldap_host = "ldap://192.168.3.1";//LDAP 服务器地址 $ldap_port = "389";//LDAP 服务器端口号 $ldap_user = "";//设定服务器用户名 $ldap_pwd = "";//设定服务器密码 $ldap_conn = ldap_connect($ldap_host, $ldap_port) or die("Can't connect to LDAP server");//建立与 LDAP 服务器的连接 ldap_bind($ldap_conn, $ldap_user, $ldap_pwd) or die("Can't bind to LDAP server.");//与服务器绑定 $base_dn = "ou=company,o=depart";//定义要进行查询的目录 $filter_col = "mail";//定义用于查询的列 $filter_val = "*@163.com";//定义用于匹配的值 $result = ldap_search($ldap_conn, $base_dn, "($filter_col=$filter_val)");//执行查询 $count = ldap_count_entries($ldap_conn, $result);//计算查询结果中的记录数 echo "Total records count: ".$count;//输出查询结果中的记录数 ldap_unbind($ldap_conn) or die("Can't unbind from LDAP server.");//与服务器断开连接 ?>需要注意的是这里使用了通配符进行 LDAP 数据库的查询,因此,可能会有多条记录被返回。
向 LDAP 添加一条新记录使用 ldap_add 函数来完成。
ldap_add(ldap_conn, base_dn, entry)
其中,ldap_conn 是前面连接 LDAP 服务器时创建的连接对象,base_dn 是 LDAP 服务器的查询主键,entry 是储存新记录的数组。以下代码实现了向 LDAP 服务器添加一条新记录的功能。
<?php $ldap_host = "ldap://192.168.3.1";//LDAP 服务器地址 $ldap_port = "389";//LDAP 服务器端口号 $ldap_user = "";//设定服务器用户名 $ldap_pwd = "";//设定服务器密码 $ldap_conn = ldap_connect($ldap_host, $ldap_port) or die("Can't connect to LDAP server");//建立与 LDAP 服务器的连接 ldap_bind($ldap_conn, $ldap_user, $ldap_pwd) or die("Can't bind to LDAP server."); //与服务器绑定 $base_dn = "ou=company,o=depart"; //定义要进行查询的目录 $entry["givenname"] = "Simon"; //定义新记录数组 $entry["company"] = "PHP workshop"; $entry["mail"] = "[email protected]"; $entry["serial_no"] = "100001"; ldap_add($ldap_conn, $base_dn, $entry) or die("Can't add new entry!"); ldap_unbind($ldap_conn) or die("Can't unbind from LDAP server."); //与服务器断开连接 ?>
更新LDAP中的一条记录
更新LDAP中的一条记录使用ldap_modify函数来完成
ldap_modify(ldap_conn, base_dn, entry)
<?php $ldap_host = "ldap://192.168.3.1";//LDAP 服务器地址 $ldap_port = "389";//LDAP 服务器端口号 $ldap_user = "";//设定服务器用户名 $ldap_pwd = "";//设定服务器密码 $ldap_conn = ldap_connect($ldap_host, $ldap_port) or die("Can't connect to LDAP server"); //建立与 LDAP 服务器的连接 ldap_bind($ldap_conn, $ldap_user, $ldap_pwd) or die("Can't bind to LDAP server."); //与服务器绑定 $base_dn = "ou=company,o=depart"; //定义要进行查询的目录 $entry = array("company" => "PHP Workshop", "mail" => "[email protected]");//设定要修改的记录属性 ldap_modify($ldap_conn, $base_dn, $entry) or die("Can't modify entry."); //修改记录 ldap_unbind($ldap_conn) or die("Can't unbind from LDAP server."); //与服务器断开连接 ?>
删除 LDAP 中的一条记录使用 ldap_delete 函数来完成。
ldap_modify(ldap_conn, base_dn)
<?php $ldap_host = "ldap://192.168.3.1";//LDAP 服务器地址 $ldap_port = "389";//LDAP 服务器端口号 $ldap_user = "";//设定服务器用户名 $ldap_pwd = "";//设定服务器密码 $ldap_conn = ldap_connect($ldap_host, $ldap_port) or die("Can't connect to LDAP server"); //建立与 LDAP 服务器的连接 ldap_bind($ldap_conn, $ldap_user, $ldap_pwd) or die("Can't bind to LDAP server.");//与服务器绑定 $base_dn = "ou=company,o=depart"; //定义要进行查询的目录 ldap_delete($ldap_conn, $base_dn) or die("Can't delete entry."); //修改记录 ldap_unbind($ldap_conn) or die("Can't unbind from LDAP server."); //与服务器断开连接 ?>
PHP 还提供了对 LDAP 操作的错误处理的方法。主要包括 3 个函数——ldap_errno、ldap_error 和ldap_err2str。ldap_errno 的语法格式如下所示。int ldap_errno(resource)其中 resource 是在 LDAP 操作中产生的对象,该函数将返回一个错误代码。ldap_error 的语法格式如下所示。
string ldap_error(resource)
string ldap_error(int errno)
<!--?php <br ?--> $ldap_host = "ldap://192.168.3.44";//LDAP 服务器地址 $ldap_port = "389";//LDAP 服务器端口号 $ldap_user = "";//设定服务器用户名 $ldap_pwd = "";//设定服务器密码 $ldap_conn = ldap_connect($ldap_host, $ldap_port);//建立与 LDAP 服务器的连接 @ldap_bind($ldap_conn, $ldap_user, $ldap_pwd);//与服务器绑定 echo "Error number: ".ldap_errno($ldap_conn)." ";//输出错误代码 echo "Error message: ".ldap_error($ldap_conn)." ";//输出错误信息 echo ldap_err2str(ldap_errno($ldap_conn));//输出错误信息 ?>
在实际应用中,可能会需要多个应用使用一个共同的用户名和密码来登陆。例如,一个企业使用多个系统来处理员工的日常操作,所有的系统均使用来自同一个LDAP目录的用户信息进行身份验证。这样,就不需要在每个系统中保存不同的密码,只需要在LDAP目录中保存一个密码即可。使用LDAP验证用户身份的原理与上一节中介绍的绑定LDAP服务器的方法相同。不同的验证时的用户名和密码来自用户的输入。完整代码如下
<?php if (!isset($_SERVER['PHP_AUTH_USER'])) { Header("WWW-Authenticate: Basic realm=\"login\""); Header("HTTP/1.0 401 Unauthorized"); } else { $ldap_host = "ldap://192.168.3.1"; $ldap_port = "389"; $ldap_user = $_SERVER['PHP_AUTH_USER']; $ldap_pwd = $_SERVER['PHP_AUTH_PW']; $ldap_conn = ldap_connect($ldap_host, $ldap_port) or die("Can't connect to LDAP server"); @ldap_bind($ldap_conn, $ldap_user, $ldap_pwd);if(ldap_errno($ldap_conn)!=0) { echo "Can't log in! ".ldap_error($ldap_conn)."<br>"; } else { echo "Welcome $ldap_user"; } } ?>