LDAP目录服务折腾之后的总结

前言

公司管理员工信息以及组织架构的后台系统要和Active Directory目录服务系统打通,后台系统使用PHP开发,

折腾了二十多天,终于上线了,期间碰到过各种疑难问题,不过总算在GOOGLE大叔的帮忙下还有运维部AD管理员的帮助下解决了。

LDAP协议定义

LDAP(Lightweight Directory Access Protocol)轻量目录访问协议,定义了目录服务实现以及访问规范。

目录定义

A directory is a specialized database specifically designed for searching and browsing, 
in additional to supporting basic lookup and update functions.

LDAP协议实现

0.基于TCP/IP的应用层协议 默认端口389 加密端口636
1.客户端发送命令,服务器端响应
2.目录主要操作
    2.0 用户验证(bind操作)
     2.1 添加节点
     2.2 更新节点
     2.3 移动节点
     2.4 删除节点
     2.5 节点搜索
3.节点类型
    3.0 节点属性规范(SCHEMA)
4.节点
    4.0 目录里的对象
     4.1 属性即是节点的数据
     4.2 目录中通过DN(Distinguished Name)唯一标识(可以认为是路径)
     4.2.0 节点DN = RDN(Relative Distinguished Name) + 父节点的DN
     4.3 目录是TREE结构,节点可以有子节点,也可以有父节点
5.属性
    5.0 同一个属性可以有多个值
     5.1 包含属性名称,属性类型
6.节点唯一标识DN说明
    6.0 示例: dn:CN=John Doe,OU=Texas,DC=example,DC=com
     6.1 从右到左 根节点 -> 子节点
     6.2 DC:所在控制域 OU:组织单元 CN:通用名称
7.目录规范(SCHEMA)
    7.0 目录节点相关规则
     7.1 Attribute Syntaxes
     7.2 Matching Rules
     7.3 Matching Rule Uses
     7.4 Attribute Types
     7.5 Object Classes
     7.6 Name Forms
     7.7 Content Rules
     7.8 Structure Rule

LDAP服务器端的实现

openLDAP,Active Directory(Microsoft)等等,除了实现协议之外的功能,还对它进行了扩展

LDAP应用场景

0.单点登录(用户管理)
1.局域网资源统一管理

封装的简单PHP类

适合AD服务器 其他的LDAP服务器需要做相应的修改

zend框架有个开源的LDAP库实现 完全面向对象

 View Code

辅助PHP类---汉字转拼音

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
<?php
/**
 * @desc 汉字转拼音 参考 http://www.php100.com/html/webkaifa/PHP/PHP/2012/0820/10914.html
 */
class o_lib_helper_pinyin{
    private $_DataKey = "a|ai|an|ang|ao|ba|bai|ban|bang|bao|bei|ben|beng|bi|bian|biao|bie|bin|bing|bo|bu|ca|cai|can|cang|cao|ce|ceng|cha
        |chai|chan|chang|chao|che|chen|cheng|chi|chong|chou|chu|chuai|chuan|chuang|chui|chun|chuo|ci|cong|cou|cu|
        cuan|cui|cun|cuo|da|dai|dan|dang|dao|de|deng|di|dian|diao|die|ding|diu|dong|dou|du|duan|dui|dun|duo|e|en|er
        |fa|fan|fang|fei|fen|feng|fo|fou|fu|ga|gai|gan|gang|gao|ge|gei|gen|geng|gong|gou|gu|gua|guai|guan|guang|gui
        |gun|guo|ha|hai|han|hang|hao|he|hei|hen|heng|hong|hou|hu|hua|huai|huan|huang|hui|hun|huo|ji|jia|jian|jiang
        |jiao|jie|jin|jing|jiong|jiu|ju|juan|jue|jun|ka|kai|kan|kang|kao|ke|ken|keng|kong|kou|ku|kua|kuai|kuan|kuang
        |kui|kun|kuo|la|lai|lan|lang|lao|le|lei|leng|li|lia|lian|liang|liao|lie|lin|ling|liu|long|lou|lu|lv|luan|lue
        |lun|luo|ma|mai|man|mang|mao|me|mei|men|meng|mi|mian|miao|mie|min|ming|miu|mo|mou|mu|na|nai|nan|nang|nao|ne
        |nei|nen|neng|ni|nian|niang|niao|nie|nin|ning|niu|nong|nu|nv|nuan|nue|nuo|o|ou|pa|pai|pan|pang|pao|pei|pen
        |peng|pi|pian|piao|pie|pin|ping|po|pu|qi|qia|qian|qiang|qiao|qie|qin|qing|qiong|qiu|qu|quan|que|qun|ran|rang
        |rao|re|ren|reng|ri|rong|rou|ru|ruan|rui|run|ruo|sa|sai|san|sang|sao|se|sen|seng|sha|shai|shan|shang|shao|
        she|shen|sheng|shi|shou|shu|shua|shuai|shuan|shuang|shui|shun|shuo|si|song|sou|su|suan|sui|sun|suo|ta|tai|
        tan|tang|tao|te|teng|ti|tian|tiao|tie|ting|tong|tou|tu|tuan|tui|tun|tuo|wa|wai|wan|wang|wei|wen|weng|wo|wu
        |xi|xia|xian|xiang|xiao|xie|xin|xing|xiong|xiu|xu|xuan|xue|xun|ya|yan|yang|yao|ye|yi|yin|ying|yo|yong|you
        |yu|yuan|yue|yun|za|zai|zan|zang|zao|ze|zei|zen|zeng|zha|zhai|zhan|zhang|zhao|zhe|zhen|zheng|zhi|zhong|
        zhou|zhu|zhua|zhuai|zhuan|zhuang|zhui|zhun|zhuo|zi|zong|zou|zu|zuan|zui|zun|zuo";
    private $_DataValue = "-20319|-20317|-20304|-20295|-20292|-20283|-20265|-20257|-20242|-20230|-20051|-20036|-20032|-20026|-20002|-19990
        |-19986|-19982|-19976|-19805|-19784|-19775|-19774|-19763|-19756|-19751|-19746|-19741|-19739|-19728|-19725
        |-19715|-19540|-19531|-19525|-19515|-19500|-19484|-19479|-19467|-19289|-19288|-19281|-19275|-19270|-19263
        |-19261|-19249|-19243|-19242|-19238|-19235|-19227|-19224|-19218|-19212|-19038|-19023|-19018|-19006|-19003
        |-18996|-18977|-18961|-18952|-18783|-18774|-18773|-18763|-18756|-18741|-18735|-18731|-18722|-18710|-18697
        |-18696|-18526|-18518|-18501|-18490|-18478|-18463|-18448|-18447|-18446|-18239|-18237|-18231|-18220|-18211
        |-18201|-18184|-18183|-18181|-18012|-17997|-17988|-17970|-17964|-17961|-17950|-17947|-17931|-17928|-17922
        |-17759|-17752|-17733|-17730|-17721|-17703|-17701|-17697|-17692|-17683|-17676|-17496|-17487|-17482|-17468
        |-17454|-17433|-17427|-17417|-17202|-17185|-16983|-16970|-16942|-16915|-16733|-16708|-16706|-16689|-16664
        |-16657|-16647|-16474|-16470|-16465|-16459|-16452|-16448|-16433|-16429|-16427|-16423|-16419|-16412|-16407
        |-16403|-16401|-16393|-16220|-16216|-16212|-16205|-16202|-16187|-16180|-16171|-16169|-16158|-16155|-15959
        |-15958|-15944|-15933|-15920|-15915|-15903|-15889|-15878|-15707|-15701|-15681|-15667|-15661|-15659|-15652
        |-15640|-15631|-15625|-15454|-15448|-15436|-15435|-15419|-15416|-15408|-15394|-15385|-15377|-15375|-15369
        |-15363|-15362|-15183|-15180|-15165|-15158|-15153|-15150|-15149|-15144|-15143|-15141|-15140|-15139|-15128
        |-15121|-15119|-15117|-15110|-15109|-14941|-14937|-14933|-14930|-14929|-14928|-14926|-14922|-14921|-14914
        |-14908|-14902|-14894|-14889|-14882|-14873|-14871|-14857|-14678|-14674|-14670|-14668|-14663|-14654|-14645
        |-14630|-14594|-14429|-14407|-14399|-14384|-14379|-14368|-14355|-14353|-14345|-14170|-14159|-14151|-14149
        |-14145|-14140|-14137|-14135|-14125|-14123|-14122|-14112|-14109|-14099|-14097|-14094|-14092|-14090|-14087
        |-14083|-13917|-13914|-13910|-13907|-13906|-13905|-13896|-13894|-13878|-13870|-13859|-13847|-13831|-13658
        |-13611|-13601|-13406|-13404|-13400|-13398|-13395|-13391|-13387|-13383|-13367|-13359|-13356|-13343|-13340
        |-13329|-13326|-13318|-13147|-13138|-13120|-13107|-13096|-13095|-13091|-13076|-13068|-13063|-13060|-12888
        |-12875|-12871|-12860|-12858|-12852|-12849|-12838|-12831|-12829|-12812|-12802|-12607|-12597|-12594|-12585
        |-12556|-12359|-12346|-12320|-12300|-12120|-12099|-12089|-12074|-12067|-12058|-12039|-11867|-11861|-11847
        |-11831|-11798|-11781|-11604|-11589|-11536|-11358|-11340|-11339|-11324|-11303|-11097|-11077|-11067|-11055
        |-11052|-11045|-11041|-11038|-11024|-11020|-11019|-11018|-11014|-10838|-10832|-10815|-10800|-10790|-10780
        |-10764|-10587|-10544|-10533|-10519|-10331|-10329|-10328|-10322|-10315|-10309|-10307|-10296|-10281|-10274
        |-10270|-10262|-10260|-10256|-10254";
    private $_Data array();
     
    public function __construct(){
        $_TDataKey explode('|'str_replace(array("\t","\n","\r\n",' '),array('','','',''),$this->_DataKey));
        $_TDataValue explode('|'str_replace(array("\t","\n","\r\n",' '),array('','','',''),$this->_DataValue));
        $_Data = (PHP_VERSION>='5.0') ? array_combine($_TDataKey$_TDataValue) : $this->_Array_Combine($_TDataKey$_TDataValue);
        arsort($_Data);
        $this->_Data = $_Data;
    }
     
    public function Pinyin($_String$_Code='gb2312'){
        reset($this->_Data);
        if($_Code != 'gb2312'$_String $this->_U2_Utf8_Gb($_String);
        $_Res '';$_aRes array();$_en '';
        for($i=0; $i<strlen($_String); $i++)
        {
            $_P = ord(substr($_String$i, 1));
            if($_P < 160){
                $_en .= chr($_P);
                continue;
            }
            if($_en){
                $_aRes[] = $_en;
                $_en '';
            }
            if($_P>160) { $_Q = ord(substr($_String, ++$i, 1)); $_P $_P*256 + $_Q - 65536; }
            //$_Res .= _Pinyin($_P, $_Data);
            $_aRes[] = $this->_Pinyin($_P$this->_Data);
        }
        foreach($_aRes as $k => $v){
            $v = preg_replace("/[^a-zA-Z0-9]*/"''$v);
            $v = ucfirst($v);
            $_aRes[$k] = $v;
        }
        return implode(' ',$_aRes);
        //return preg_replace("/[^a-zA-Z0-9]*/", '', $_Res);
    }
     
    private function _Pinyin($_Num$_Data){
        if ($_Num>0 && $_Num<160 ) return chr($_Num);
        elseif($_Num<-20319 || $_Num>-10247) return '';
        else {
        foreach($_Data as $k=>$v){ if($v<=$_Numbreak; }
        return $k;
        }
    }
     
    private function _U2_Utf8_Gb($_C){
        $_String '';
        if($_C < 0x80) $_String .= $_C;
        elseif($_C < 0x800)
        {
            $_String .= chr(0xC0 | $_C>>6);
            $_String .= chr(0x80 | $_C & 0x3F);
        }elseif($_C < 0x10000){
            $_String .= chr(0xE0 | $_C>>12);
            $_String .= chr(0x80 | $_C>>6 & 0x3F);
            $_String .= chr(0x80 | $_C & 0x3F);
        elseif($_C < 0x200000) {
            $_String .= chr(0xF0 | $_C>>18);
            $_String .= chr(0x80 | $_C>>12 & 0x3F);
            $_String .= chr(0x80 | $_C>>6 & 0x3F);
            $_String .= chr(0x80 | $_C & 0x3F);
        }
        return iconv('UTF-8''GB2312'$_String);
    }
     
    private function _Array_Combine($_Arr1$_Arr2){
        for($i=0; $i<count($_Arr1); $i++) $_Res[$_Arr1[$i]] = $_Arr2[$i];
        return $_Res;
    }
}

辅助PHP类---简单TREE处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
<?php
/**
 * @description 简单tree类
 *
 * @author WadeYu
 * @date 2015-04-30
 * @version 0.0.1
 */
class o_simpletree{
    private $_aNodeList array(); // [id => []]
    private $_aChildNodeList array(); // [parentId => [childId,childId,]]
    private $_aTopNodeList array(); //[id => []]
    private $_pk '';
    private $_parentPk '';
    private $_aTreeKV array(); //tree key的显示的内容
    private $_aJoinKey array();
     
    public function __construct(array $aData array()/*[[id:0,fid:1],[]]*/array $aOption array()){
        $this->_pk = $aOption['pk'];
        $this->_parentPk = $aOption['parentPk'];
        $this->_aTreeKV = (array)$aOption['aTreeKV'];
        $this->_mkNodeList($aData);
        $this->_mkChildNodeList();
    }
     
    public function getTree($parentPk){
        $aRet array();
        $aChild array();
        if (!isset($this->_aChildNodeList[$parentPk])){
            return $aRet;
        }
        $aChild $this->_aChildNodeList[$parentPk];
        foreach((array)$aChild as $k => $v){
            $currNode $this->_aNodeList[$v];
            $tmpK '';
            $i = 0;
            foreach($this->_aTreeKV as $k2 => $v2){
                $tmpV $currNode[$v2];
                if($i == 0){
                    $tmpK .= $tmpV;
                else if ($i == 1){
                    $tmpK .= "({$tmpV})";
                else if ($i == 2){
                    $tmpK .= "[{$tmpV}]";
                }
                $i++;
            }
            if (isset($this->_aChildNodeList[$v])){
                $aRet[$tmpK] = $this->getTree($v);
            else {
                $aRet[$tmpK] = 1;
            }
        }
        return $aRet;
    }
     
    public function joinKey($aTree,$prefix ''){
        $prefix = trim($prefix);
        if(!is_array($aTree)){
            return $prefix;
        }
        foreach((array)$aTree as $k => $v){
            if (is_array($v)){
                $this->joinKey($v,"{$prefix}{$k}/");
            else {
                $this->_aJoinKey["{$prefix}{$k}"] = 1;
            }
        }
        return true;
    }
     
    public function getJoinKey(){
        return $this->_aJoinKey;
    }
     
    private function _mkNodeList(array $aData array()){
        foreach($aData as $k => $v){
            $this->_aNodeList[$v[$this->_pk]] = $v;
        }
    }
     
    private function _mkChildNodeList(){
        foreach($this->_aNodeList as $k => $v){
            if ($v['fid']){
                $this->_aChildNodeList[$v[$this->_parentPk]][] = $v[$this->_pk];
            else {
                $this->_aTopNodeList[$v[$this->_pk]] = $v;
            }
        }
    }
}

  

 

 

LDAP开源实现:openLDAP

0.相关环境说明
    a.操作系统

复制代码

1 [root@vm ldap]# lsb_release -a2 LSB Version:    :core-3.1-amd64:core-3.1-ia32:core-3.1-noarch:graphics-3.1-amd64:graphics-3.1-ia32:graphics-3.1-noarch3 Distributor ID:    CentOS4 Description:    CentOS release 5.4 (Final)5 Release:    5.46 Codename:    Final

复制代码

 1.安装

    a.yum -y install openldap-servers openldap-clients

2.配置
    a.配置HOST
        [root@vm ldap]# vi /etc/hosts
       127.0.0.1 test.com
     b.创建证书

+ View Code

   c.生成管理员密码

            root@vm ~]# slappasswd 

            New password: 
           Re-enter new password: 
          {SSHA}2eG1IBeHhSjfgS7pjoAci1bHz5p4AVeS

    d.配置slapd.conf
        [root@vm certs]# vi /etc/openldap/slapd.conf

       去掉TLS相关注释

       设置数据库配置

    e.BerkeleyDb配置

        [root@vm certs]# cd /etc/openldap/
        [root@vm openldap]# mv ./DB_CONFIG.example /var/lib/ldap/DB_CONFIG

    f.配置ldap.conf

        [root@vm openldap]# vi ldap.conf

    g.开启加密支持
        [root@vm ~]# vim /etc/sysconfig/ldap
        SLAPD_LDAPS=yes

3.使用slapadd命令添加根节点 未启动前

复制代码

1 [root@vm ~]# cd ~2 [root@vm ~]# vim root.ldif3 dn: dc=test,dc=com4 dc: test5 objectClass: dcObject6 objectClass: organizationalUnit7 ou: test.com8 [root@vm ~]# slapadd -v -n 1 -l root.ldif

复制代码

4.启动slapd
[root@vm ~]# slapd -h "ldap:// ldaps://"
389非加密端口 636加密端口

5.检测

+ View Code

  

6.phpldapadmin客户端访问
    a.官网下载源码放入WEB目录下 下载页面:http://phpldapadmin.sourceforge.net/wiki/index.php/Download
    b.安装依赖的扩展gettext ldap这2个扩展
    c.按需配置 源码目录下config/config.php

问题

1.ldaps无法访问
/etc/openldap/ldap.conf TLS_REQCERT never加上这个

源码安装PHP扩展步骤

1.下载PHP源码
2.切换到扩展源码所在目录 示例:cd /src path/ext/extname
3.执行phpize命令 (1.PHP源代码或者PHP安装目录包含此命令 2.当前目录会生成一个检查编译扩展的环境脚本configure)
4../configure --with-php-config=/usr/local/php/bin/php-config (1.编译环境配置检查 2.生成make命令需要的编译配置文件makefile)
5.make && make install (编译安装)
6.php.ini 加上配置 extension = "xxxxx.so"
7.重启php service php-fpm restart

安装PHP LDAP扩展

示例:centos系统安装LDAP扩展
1.安装依赖库openldap openldap-devel
yum install openldap 
yum install openldap-devel
2.参考:源码安装PHP扩展步骤

 

补充(最新LDAP操作类LARAVEL框架版)

LDAP基础类

 View Code

组织架构信息更新类

 View Code

 查看客户端

ApacheDirectoryStudio-win32-x86_64-2.0.0.v20130628

 

参考资料

[1] LDAPV3协议

http://tools.ietf.org/html/rfc4511

[2] LDAP百度百科

http://baike.baidu.com/view/159263.htm

[3] WIKI LDAP

http://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol

[4] LDAP Data Interchange Format

http://en.wikipedia.org/wiki/LDAP_Data_Interchange_Format

[5] OpenLDAP介绍

http://en.wikipedia.org/wiki/OpenLDAP

[6] OpenLDAP管理员文档

[7] Zend LDAP API

http://framework.zend.com/manual/1.11/en/zend.ldap.api.html

[8] BerkeleyDb以及OPENLDAP安装指南

http://www.openldap.org/lists/openldap-technical/201001/msg00046.html

[9] LDAP环境搭建 OpenLDAP和phpLDAPadmin -- yum版

http://www.cnblogs.com/yafei236/p/4141897.html

[10] phpldapadmin开源项目

http://phpldapadmin.sourceforge.net/wiki/index.php/Main_Page

作者:WadeYu 
出处:http://www.cnblogs.com/wadeyu/ 
本文版权归本人和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章