前段時間一直在做LDAP+POSTFIX相關項目,先把關于LDAP的一些經驗寫出來,一來可能會幫助一些人,二來對我自己所學知識也是一個鞏固。)
先聲明:我寫的隻是我對LDAP的一些了解,如果我的了解錯誤,那就是對兄弟們的誤導。是以你可以直接看文章的結尾提供的幾個網址。
關于LDAP的概念随便網上有很多,我不想重複,這裡隻是說一下我自己的了解。
都說它是“輕量級目錄協定”,太專業,我不懂,我隻把它想象成“簡單”的目錄協定。
幾個很重要的概念,以後會用到:
---------------------------------------------
dn :一條記錄的位置
dc :一條記錄所屬區域
ou :一條記錄所屬組織
cn/uid:一條記錄的名字/ID
實際上更多時候我隻把它看成資料庫。我把它和我非常熟悉的MYSQL資料庫做比較,通常會得到更好的了解:
MYSQL用“表”儲存資料,LDAP用“樹”
MYSQL指定一條記錄要3個條件:DB、TABLE、ROW。
LDAP卻更自由,為什麼呢?因為LDAP資料是“樹”狀的,而且這棵樹是可以無限延伸的,假設你要樹上的一個蘋果(一條記錄),你怎麼告訴園丁它的位置呢?當然首先要說明是哪一棵樹(dc,相當于MYSQL的DB),然後是從樹根到那個蘋果所經過的所有“分叉”(ou,呵呵MYSQL裡面好象沒有這DD),最後就是這個蘋果的名字(uid,記得我們設計MYSQL或其它資料庫表時,通常為了友善管理而加上一個‘id’字段嗎?)。 好了!這時我們可以清晰的指明這個蘋果的位置了,就是那棵“歪脖樹”的東邊那個分叉上的靠西邊那個分叉的再靠北邊的分叉上的半紅半綠的……,暈了!你直接爬上去吧!我還是說說LDAP裡要怎麼定義一個字段的位置吧,樹(dc=waibo,dc=com),分叉(ou=bei,ou=xi,ou=dong),蘋果(cn=honglv),好了!位置出來了:
dn:cn=honglv,ou=bei,ou=xi,ou=dong,dc=waibo,dc=com
一個有名的畫家說過:“世上沒有相同的2個雞蛋”。當然也沒有相同的2個蘋果……,同樣,在LDAP裡也不可能存在2個相同的dn。
LDAP資料填充原理:
一棵樹的生長,要循序漸進,如果還沒有長出某個分叉,就不可能在那個分叉裡長出蘋果(問:FT!蘋果是長在分叉上的嗎?答:為了便于了解,你就當它是吧),同樣,LDAP資料庫也要一步步的充實,舉一個學校資料庫的例子,我們将要把一個龐大的學生檔案放到LDAP裡,大緻需要這麼做:
1、建立“樹根”,這是通過修改“slapd.conf”來實作的,由于現在的目的是了解,是以具體步驟就不說了,反正就是在這一步建立了一個“dc=ourschool,dc=org”這樣一個“樹根”。 注意:我把它了解成“目錄”,或者“容器”,甚至它本身也是檔案(蘋果)的特殊形式,熟悉LINUX檔案系統的朋友會更容易了解。
2、建立18個系,分别是“dn:ou=computer,dc=ourschool,dc=org”、“dn:ou=film,dc=ourschool,dc=org”……
3、當然是在每個系裡面建立專業,比如“dn:ou=linux,ou=computer,dc=ourschool,dc=org”……
4、(開始長蘋果吧!)加學生喽——“dn:cn=stan,ou=linux,ou=computer,dc=ourschool,dc=org”……
5、已經完成了嗎?對了!學生的詳細資訊還沒有呐!不過先這樣吧,反正記錄是可以編輯的。
當你引用硬碟上的檔案時,通常是這樣的:
正斜杠(/)在這裡表示級别分界線,并且從左向右閱讀。
而在LDAP中則通過"distinguished name"(簡稱"dn")來表示檔案,通常像下面這樣:
逗号(,)在這裡表示級别分界線,并且從右向左閱讀。上述dn可以了解為:
術語對比:
與硬碟目錄一樣,目錄伺服器上的目錄結構也沒有任何限制,這就意味着你必須了解一些伺服器的結構資訊才能寫程式。
更多關于LDAP的資訊可以在下面兩個URL找到:
<a href="https://wiki.mozilla.org/Directory" target="_blank">Mozilla</a>
<a href="http://www.openldap.org/" target="_blank">OpenLDAP Project</a>
LDAP子產品的行為受下面的配置指令的影響
指令
資料類型
作用域
預設值
解釋
ldap.max_links
整數
PHP_INI_SYSTEM
-1
每程序允許的最大LDAP連接配接數。"-1"表示無限制。
在進行LDAP程式設計之前,你必須知道目錄伺服器的下列資訊:
伺服器的IP位址(主機名)以及端口号
伺服器的"base dn"(也就是"the world"目錄下的子目錄,比如:"o=My Company,c=US")
通路伺服器的使用者名(RDN)和密碼(許多伺服器允許"匿名綁定"來讀取資訊,但是其他操作必須有密碼才行)
一般的LDAP程式設計步驟如下:
ldap_connect() // 連接配接到LDAP伺服器
ldap_bind() // 匿名登陸或者認證登陸
做一些操作,比如讀取、添加、删除等...
ldap_unbind() // 關閉連接配接
<dl></dl>
<dt>resource ldap_connect ([ string hostname=NULL[,inthostname=NULL[,intport = 389 ]] )</dt>
<dd></dd>
使用指定的主機名(hostname)和端口(hostname)和端口(port)連接配接到LDAP伺服器。
<dt>$hostname</dt>
<dd>主機名,如果伺服器端是 OpenLDAP 2.x.x 或更高版本,那麼還可以使用 ldap://hostname/ 格式(URL格式)。</dd>
要使用SSL連接配接,那麼必須確定OpenLDAP和PHP都帶有SSL支援,并使用 ldaps://hostname/ 的格式。
如果使用空格分隔的主機名清單(比如"192.168.0.100:389 192.168.0.101"),那麼此函數将依次嘗試直到連接配接成功為止。
<dt>$port</dt>
<dd>連接配接的端口(預設為389)。在使用URL格式的時候不需要使用此參數,直接在URL裡面指明即可(ldap://hostname:port/)。</dd>
連接配接成功則傳回一個LDAP連接配接辨別符,連接配接失敗則傳回 FALSE 。
如果伺服器端是 OpenLDAP 2.x.x 或更高版本,那麼此函數将始終傳回一個LDAP連接配接辨別符,而永遠不會失敗。實際的連接配接動作将在接下來調用 ldap_* 函數[通常是ldap_bind()]時執行。
如果不帶任何參數調用此函數,則傳回上一次連接配接已經打開的連接配接辨別符。
<dt>bool ldap_bind ( resource linkidentifier[,stringlinkidentifier[,stringbind_rdn = NULL [, string $bind_password = NULL ]] )</dt>
使用指定的RDN(bindrdn)和密碼(bindrdn)和密碼(bind_password)綁定到LDAP目錄。
<dt>$link_identifier</dt>
<dd>ldap_connect()函數傳回的LDAP連接配接辨別符</dd>
<dt></dt>
bindrdnbindrdnbind_password
<dd>綁定時使用的RDN(Relative Distinguished Name)和密碼。如果未指定則使用匿名認證。</dd>
綁定成功傳回 TRUE 否則傳回 FALSE 。
<dt>string ldap_error ( resource $link_identifier )</dt>
檢索LDAP操作的錯誤資訊。
傳回指定的連接配接辨別符上最近一次LDAP操作的錯誤資訊。
<dt>bool ldap_get_option ( resource linkidentifier,intlinkidentifier,intoption , mixed &retval)boolldapsetoption(resourceretval)boolldapsetoption(resourcelink_identifier , int option,mixedoption,mixednewval )</dt>
擷取/設定LDAP選項的值。
<dt>$option</dt>
<dd>LDAP選項名稱,主要的選項及其資料類型如下:</dd>
<dd><dl></dl></dd>
<dt>LDAP_OPT_DEREF(int)</dt>
<dd>搜尋的時候如何處理别名,取值範圍如下:LDAP_DEREF_NEVER(0,預設值), LDAP_DEREF_SEARCHING(1), LDAP_DEREF_FINDING(2), LDAP_DEREF_ALWAYS(3)</dd>
<dt>LDAP_OPT_NETWORK_TIMEOUT(int)</dt>
<dd>網絡逾時秒數,LDAP_NO_LIMIT(0,預設值)表示永不逾時。</dd>
<dt>LDAP_OPT_PROTOCOL_VERSION(int)</dt>
<dd>指定使用的LDAP協定版本,取值範圍如下:LDAP_VERSION2(2,預設值), LDAP_VERSION3 (3)。</dd>
<dt>LDAP_OPT_REFERRALS(bool)</dt>
<dd>LDAP庫是否自動追随LDAP伺服器傳回的引用,取值範圍如下:TRUE(1,預設值), FALSE(0)。</dd>
<dt>&$retval</dt>
<dd>接受選項值的變量</dd>
<dt>$newval</dt>
<dd>選項的新值</dd>
擷取/設定成功傳回 TRUE 否則傳回 FALSE 。
<dt>bool ldap_add ( resource linkidentifier,stringlinkidentifier,stringdn , array entry)boolldapdelete(resourceentry)boolldapdelete(resourcelink_identifier , string $dn )</dt>
在LDAP目錄中添加/删除一個項。
<dt>$dn</dt>
<dd>将要添加/删除的項目名稱(distinguished name)。</dd>
<dt>$entry</dt>
<dd>指定新項内容的關聯數組(attribute=>value)。如果value也是一個數組,那麼必須是從0開始的索引數組。例如:</dd>
添加/删除成功傳回 TRUE 否則傳回 FALSE 。
<dt>mixed ldap_compare ( resource linkidentifier,stringlinkidentifier,stringdn , string attribute,stringattribute,stringvalue )</dt>
檢查LDAP目錄項dn的dn的attribute屬性值與給定的$value是否相同。注意:不能用來比較二進制資料!
<dd>LDAP項的名稱(distinguished name)</dd>
<dt>$attribute</dt>
<dd>屬性名</dd>
<dt>$value</dt>
<dd>給定的值</dd>
相同傳回 TRUE ,不同傳回 FALSE ,遇見錯誤傳回 -1
<dt>resource ldap_read ( resource linkidentifier,stringlinkidentifier,stringbase_dn , string filter[,arrayfilter[,arrayattributes [, int attrsonly[,intattrsonly[,intsizelimit [, inttimelimit[,inttimelimit[,intderef ]]]]] )</dt>
resource ldap_list ( resource linkidentifier,stringlinkidentifier,stringbase_dn , string filter[,arrayfilter[,arrayattributes [, int attrsonly[,intattrsonly[,intsizelimit [, int timelimit[,inttimelimit[,intderef ]]]]] )
resource ldap_search ( resource linkidentifier,stringlinkidentifier,stringbase_dn , string filter[,arrayfilter[,arrayattributes [, int attrsonly[,intattrsonly[,intsizelimit [, int timelimit[,inttimelimit[,intderef ]]]]] )
使用指定的過濾器搜尋LDAP目錄。三個函數的不同之處在于搜尋範圍不同:
read僅搜尋basedn本身(LDAPSCOPEBASE),相當于從目錄中讀取一個條目(entry)。list僅搜尋basedn本身(LDAPSCOPEBASE),相當于從目錄中讀取一個條目(entry)。list僅搜尋base_dn的下一級對象(LDAP_SCOPE_ONELEVEL),不包含本身,相當于"ls"指令。
search搜尋$base_dn本身及其所有子對象(LDAP_SCOPE_SUBTREE),相當于搜尋整個目錄樹。
<dt>$base_dn</dt>
<dd>将要被搜尋的目錄的DN</dd>
<dt>$filter</dt>
<dd>搜尋過濾器。比如"(objectClass=*)"表示搜尋所有條目(對于read函數則表示所有屬性)。</dd>
<dt>$attributes</dt>
<dd>需要檢索的屬性名稱數組,比如:array("mail", "sn", "cn")。</dd>
注意:不管有沒有指定,"dn"屬性的值總會被傳回。
如果不指定此參數,那麼将傳回所有的屬性值。
<dt>$attrsonly</dt>
<dd>預設值"0"表示同時擷取屬性的類型(attribute type)和屬性的值(attribute value)。</dd>
非預設值"1"表示僅擷取屬性的類型(attribute type)。
<dt>$sizelimit</dt>
<dd>限定最多傳回多少條記錄。預設值"0"表示沒有限制。注意:這個參數不能超越伺服器的限制。</dd>
<dt>$timelimit</dt>
<dd>限定搜尋操作最大允許進行多少秒。預設值"0"表示沒有限制。注意:這個參數不能超越伺服器的限制。</dd>
<dt>$deref</dt>
<dd>指定搜尋的時候如何處理别名。取值範圍如下:</dd>
<dt>LDAP_DEREF_NEVER(預設)</dt>
<dd>在搜尋中或者查找那基礎對象時做不複引用别名</dd>
<dt>LDAP_DEREF_SEARCHING</dt>
<dd>在基礎對象的附屬的搜尋中而不是查找那基礎對象時做複引用别名</dd>
<dt>LDAP_DEREF_FINDING</dt>
<dd>在基礎對象而不是其附屬的搜尋中做複引用别名</dd>
<dt>LDAP_DEREF_ALWAYS</dt>
<dd>在搜尋中或者查找那基礎對象時做都複引用别名</dd>
成功傳回一個結果集的資源描述符,通常被其他函數以$result_identifier引用,失敗傳回FALSE
<dt>array ldap_get_entries ( resource linkidentifier,resourcelinkidentifier,resourceresult_identifier )</dt>
傳回前一次搜尋操作的結果集,包括每一項的屬性和屬性值。
<dt>$result_identifier</dt>
<dd>ldap_read/ldap_list/ldap_search函數傳回的結果集的資源描述符。</dd>
成功傳回一個包含結果集的多元數組,失敗傳回FALSE。
注意:結果集數組的屬性索引将被轉換成小寫字母(對于LDAP來說屬性是大小寫無關的)。
結果集數組的結構如下所示:
<dt>bool ldap_unbind ( resource $link_identifier )</dt>
解除綁定,也就是關閉LDAP連接配接。
成功傳回 TRUE 否則傳回 FALSE 。
本文轉自二郎三郎部落格園部落格,原文連結:http://www.cnblogs.com/haore147/p/7172184.html,如需轉載請自行聯系原作者