4

由于项目需要实现SSO单点登录的功能,所以,这里借用LDAP实现,LDAP的优点是不使用数据库就可在服务器建立一种权限关系。

一、LDAP简介

LDAP 的全称是“轻量级目录访问协议 (Lightweight Directory Access Protocol)”,是一种简单的目录协议。所谓目录,是一种专门的数据库,可以用来服务于任何应用程序。公司的域帐号登录采用的是Ldap登录验证,所有的系统均使用来自同一个 LDAP 目录的用户信息进行身验证。这样,就不需要在每个系统中保存不同的密码,只需要在 LDAP 目录中保存一个密码即可。本文主要介绍一下PHP环境下如何通过后台登录公司Ldap服务器验证用户名密码。

二、LDAP目录树的结构

 LDAP目录以树状的层次结构来存储数据。如果你对自顶向下的DNS树或UNIX文件的目录树比较熟悉,也就很容易掌握LDAP目录树这个概念了。就象DNS的主机名那样,LDAP目录记录的标识名(Distinguished Name,简称DN)是用来读取单个记录,以及回溯到树的顶部。

1. 基准DN

DN:标识名,简称DN (Distinguished Name,简称DN)
是用来读取单个记录,以及回溯到树的顶部。

这种格式很直观,用公司的域名作为基准DN。这也是现在最常用的格式。
dc=foobar, dc=com
(用DNS域名的不同部分组成的基准DN)

DC=Domain Component 为用户名或服务器名,最长可以到80个字符,可以为中文;
CN=Common Name 为用户名或服务器名,最长可以到80个字符,可以为中文;
OU=Organizational Unit为组织单元,最多可以有四级,每级最长32个字符,可以为中文;
O=Organization 为组织名

CN, OU, DC 都是 LDAP 连接服务器的端字符串中的区别名称(DN, distinguished name)
LDAP连接服务器的连接字串格式为:ldap://servername/DN
其中DN有三个属性,分别是CN,OU,DC
LDAP是一种通讯协议,如同HTTP是一种协议一样的!
在 LDAP 目录中,
· DC (Domain Component)
· CN (Common Name)
· OU (Organizational Unit)

LDAP 目录类似于文件系统目录。
下列目录:

DC=redmond,DC=wa,DC=microsoft,DC=com  

如果我们类比文件系统的话,可被看作如下文件路径:

Com\Microsoft\Wa\Redmond   

例如:

CN=test,OU=developer,DC=domainname,DC=com 

在上面的代码中 cn=test 可能代表一个用户名,ou=developer 代表一个 active directory 中的组织单位。这句话的含义可能就是说明 test 这个对象处在domainname.com 域的 developer 组织单元中。

三、安装LDAP

安装OpenLdap

tar zvxf openldap2.4.31.tgz  
cd /openldap2.4.31  
./configure --prefix=/usr/local/openldap  
make depend  
make  
make test  
make install  

注意: 在执行./configure的时候可能会报如下错误
configure: error: MozNSS not found – please specify the location to the NSPR and NSS header files in CPPFLAGS and the location to the NSPR and NSS libraries in LDFLAGS (if not in the system location)

原因是openldap需要依赖openssl的一些库文件,安装openldap,然后配置SSL的环境变量

root@homestead:/home/other/openldap-2.4.31# export CPPFLAGS="-I/usr/local/BerkeleyDB.5.1/include -I/usr/local/ssl/include "
root@homestead:/home/other/openldap-2.4.31# export LDFLAGS="-L/usr/local/BerkeleyDB.5.1/lib -L/usr/local/ssl/lib "

使用 find -name xxx 命令查找文件

[root@openldap openldap]# find -name slapd.conf
./slapd.conf

进入etc 配置修改

 cd /etc/openldap/

杀掉ldap:

killall slapd

查看进程:

netstat -anlt

启动slapd服务

/usr/local/openldap-2.4.31/libexec/slapd

四、使用

<?php

define('LDAP_SERVER_IP', '127.0.0.1');
define('LDAP_SERVER_PORT', 389);

// 建立到ldap服务器的连接LDAP_SERVER_IP是ldap服务器ip,LDAP_SERVER_PORT是ldap服务器端口(默认389) 
$ldapConnect = ldap_connect(LDAP_SERVER_IP, LDAP_SERVER_PORT) or die("Could not connect to " . LDAP_SERVER_IP); 

if ($ldapConnect)
{ 
   $username = "xiaowang"; 
   $upasswd  = "123456"; 
   $binddn   = "uid=$username,ou=people,dc=192.168.17.181,dc=com"; 
   $ldapbind = ldap_bind($ldapConnect);    // 匿名的 bind,为只读属性


  if($ldapbind)
  { 
        echo "login" ; 

          $sr=ldap_search($ldapConnect,"dc=".LDAP_SERVER_IP, "sn=l*");  
          print_r($sr);
  } 
  else 
  {
   echo " not login"; 
  } 

}


// 关闭连接
 ldap_close($ldapConnect);   
     

五、遇到的坑

clipboard.png
擦,出现这样的问题:

Warning: ldap_bind(): Unable to bind to server: Invalid credentials in D:\xampps\htdocs\xampps\web\ldap\index.php on line 40

使用命令在服务器端添加条目:

[root@openldap openldap]# ldapadd -x -D "cn=Chow,dc=baidu,dc=com" -W -f user.ldif
Enter LDAP Password: 
ldap_bind: Invalid credentials (49)

OpenLDAP 服务出现这样的问题,什么原因呢?

折腾了好久,原来是自己的ldap的服务器域名没有设置:

先获取ldap服务器的IP地址:

# ifconfig
192.168.17.83
# vim hostname

baidu.com

然后再配置文件中进行相应的修改。

六、phpldapadmin

clipboard.png

七、ldap的相关增删改查

<?php

define('LDAP_SERVER_IP', '192.168.1.1');
define('LDAP_SERVER_PORT', 389);

// 建立到ldap服务器的连接LDAP_SERVER_IP是ldap服务器ip,LDAP_SERVER_PORT是ldap服务器端口(默认389) 
$ldapConnect = ldap_connect(LDAP_SERVER_IP, LDAP_SERVER_PORT) or die("Could not connect to " . LDAP_SERVER_IP); 

ldap_set_option($ldapConnect, LDAP_OPT_PROTOCOL_VERSION,3) or die("Could not set ldap protocol version");


// ================= 添加people 组=====================
/*
$new_dn = "ou=People,dc=baidu,dc=com";
$ldaprecord['ou'] = "People";
$ldaprecord['objectclass'][0] = "top";
$ldaprecord['objectclass'][1] = "organizationalUnit";
*/
// ================= 添加people 组=====================
// 

if ($ldapConnect)
{ 
  
   $upasswd    = "123456"; 
   $base       = "dc=baidu,dc=com";
   $new_binddn = "cn=root,dc=baidu,dc=com";


  $ldapbind = ldap_bind($ldapConnect, $new_binddn, $upasswd) or die("bind fail");    // 匿名的 bind,为只读属性


$admin_users = array(
 array("user_name" => "张雪玉", "pinyin" => "zhangxueyu", "pwd" => "b3be5dc2e108236561fd120f6e4c654c"),
 array("user_name" => "张学友", "pinyin" => "zhangxueyou", "pwd" => "eadd934e2cc978f23654fdsadffdfdaf"),

);


  // 公共属性
  $new_dn = "ou=people,dc=baidu,dc=com";
  $ldaprecord['objectclass'][0] = "top";
  $ldaprecord['objectclass'][1] = "posixAccount";
  $ldaprecord['objectclass'][2] = "inetOrgPerson";
  $ldaprecord['gidNumber'] = "200";
  $ldaprecord['uidNumber'] = "3";
    

foreach($admin_users as $k => $v)
{
  $name   = $v['user_name'];
  $uid    = base64_encode($name);
  $pinyin = $v['pinyin'];
  $pwd    = $v['pwd'];

  // 添加属性
  $ldaprecord['cn'] = $pinyin;
  $ldaprecord['sn'] = $pinyin;
  $ldaprecord['displayName'] = $name; 
  $ldaprecord['uid'] = $uid;
  $ldaprecord['userpassword'] = $pwd;
  $ldaprecord['homeDirectory'] = "/home/users/{$pinyin}";

  $good_new_dn = "uid={$uid},{$new_dn}";

  ldap_add($ldapConnect, $good_new_dn, $ldaprecord) or die( "Can’t add new dn!" );

}

 

   // 添加

     if($ldapbind)
    { 
      echo "login" ; 

     //  $sr=ldap_search($ldapConnect, $base, 'cn=wang*');  
     //  $ret = ldap_get_entries($ldapConnect, $sr);
      $sr=ldap_search($ldapConnect, $base, "(ObjectClass=*)");  
      $ret = ldap_get_entries($ldapConnect, $sr);
      $pwd = $ret[0]['userpassword'][0];
      print_r($ret);
    } 
    else 
    {
     echo " not login"; 
    } 

}

// 删除
 $del_dn = "uid=xiaoming,ou=People,dc=baidu,dc=com";
// $res = ldap_delete($ldapConnect, $del_dn) or die( "Can’t delete dn!" );

if($res)
{
  echo 'delete success!';

}


// 更新
$update_dn = "uid=corwien,ou=People,dc=baidu,dc=com";
$update_entry = array( "userpassword"=>"10086");
// $res = ldap_mod_replace($ldapConnect, $update_dn, $update_entry) or die( "Can’t update  dn!" );
if($res)
{
  echo 'update success!';

}

// 关闭连接
 ldap_close($ldapConnect);   


     

php LDAP简介
LDAP服务器的概念和原理简单介绍
LDAP环境搭建 OpenLDAP和phpLDAPadmin -- yum版
LDAP目录服务折腾之后的总结
LDAP 中 CN, OU, DC 的含义
OpenLDAP(2.4.3x)服务器搭建及配置说明
LDAP常用命令解析
OpenLDAP编译安装及配置
LDAP的相关概念与objectClass介绍
LDAP基础概念


Corwien
6.3k 声望1.6k 粉丝

为者常成,行者常至。