什麼是LDAP?
LDAP的英文全稱是Lightweight Directory Access Protocol,一般都簡稱為LDAP。它是基于X.500标準的,
但是簡單多了并且可以根據需要定制。與X.500不同,LDAP支援TCP/IP,這對通路Internet是必須的。LDAP
的核心規範在RFC中都有定義,所有與LDAP相關的RFC都可以在LDAPman RFC網頁中找到。現在LDAP技術不僅
發展得很快而且也是激動人心的。在企業範圍内實作LDAP可以讓運作在幾乎所有計算機平台上的所有的應
用程式從LDAP目錄中擷取資訊。LDAP目錄中可以存儲各種類型的資料:電子郵件位址、郵件路由資訊、人力
資源資料、公用密匙、聯系人清單,等等。通過把LDAP目錄作為系統內建中的一個重要環節,可以簡化員工
在企業内部查詢資訊的步驟,甚至連主要的資料源都可以放在任何地方。
LDAP目錄的優勢
如果需要開發一種提供公共資訊查詢的系統一般的設計方法可能是采用基于WEB的資料庫設計方式,即前端
使用浏覽器而後端使用WEB伺服器加上關系資料庫。後端在Windows的典型實作可能是Windows NT + IIS + Acess
資料庫或者是SQL伺服器,IIS和資料庫之間通過ASP技術使用ODBC進行連接配接,達到通過填寫表單查詢資料的功能;
後端在Linux系統的典型實作可能是Linux+ Apache + postgresql,Apache和資料庫之間通過PHP3提供的函數進
行連接配接。使用上述方法的缺點是後端關系資料庫的引入導緻系統整體的性能降低和系統的管理比較繁瑣,因為需
要不斷的進行資料類型的驗證和事務的完整性的确認;并且前端使用者對資料的控制不夠靈活,使用者權限的設定一
般隻能是設定在表一級而不是設定在記錄一級。
目錄服務的推出主要是解決上述資料庫中存在的問題。目錄與關系資料庫相似,是指具有描述性的基于屬性的記
錄集合,但它的資料類型主要是字元型,為了檢索的需要添加了BIN(二進制資料)、CIS(忽略大小寫)、CES
(大小寫敏感)、TEL(電話型)等文法(Syntax),而不是關系資料庫提供的整數、浮點數、日期、貨币等類型,
同樣也不提供象關系資料庫中普遍包含的大量的函數,它主要面向資料的查詢服務(查詢和修改操作比一般是大于
10:1),不提供事務的復原(rollback)機制,它的資料修改使用簡單的鎖定機制實作All-or-Nothing,它的目标
是快速響應和大容量查詢并且提供多目錄伺服器的資訊複制功能。
現在該說說LDAP目錄到底有些什麼優勢了。現在LDAP的流行是很多因數共同作用的結果。可能LDAP最大的優勢是:
可以在任何計算機平台上,用很容易獲得的而且數目不斷增加的LDAP的用戶端程式通路LDAP目錄。而且也很容易
定制應用程式為它加上LDAP的支援。
LDAP協定是跨平台的和标準的協定,是以應用程式就不用為LDAP目錄放在什麼樣的伺服器上操心了。實際上,LDAP
得到了業界的廣泛認可,因為它是Internet的标準。産商都很願意在産品中加入對LDAP的支援,因為他們根本不用
考慮另一端(用戶端或服務端)是怎麼樣的。LDAP伺服器可以是任何一個開發源代碼或商用的LDAP目錄伺服器(或
者還可能是具有LDAP界面的關系型資料庫),因為可以用同樣的協定、用戶端連接配接軟體包和查詢指令與LDAP伺服器
進行互動。與LDAP不同的是,如果軟體産商想在軟體産品中內建對DBMS的支援,那麼通常都要對每一個資料庫服務
器單獨定制。不象很多商用的關系型資料庫,你不必為LDAP的每一個用戶端連接配接或許可協定付費 大多數的LDAP服務
器安裝起來很簡單,也容易維護和優化。
LDAP伺服器可以用“推”或“拉”的方法複制部分或全部資料,例如:可以把資料“推”到遠端的辦公室,以增加
資料的安全性。複制技術是内置在LDAP伺服器中的而且很容易配置。如果要在DBMS中使用相同的複制功能,資料庫
産商就會要你支付額外的費用,而且也很難管理。
LDAP允許你根據需要使用ACI(一般都稱為ACL或者通路控制清單)控制對資料讀和寫的權限。例如,裝置管理者可
以有權改變員工的工作地點和辦公室号碼,但是不允許改變記錄中其它的域。ACI可以根據誰通路資料、通路什麼數
據、資料存在什麼地方以及其它對資料進行通路控制。因為這些都是由LDAP目錄伺服器完成的,是以不用擔心在客
戶端的應用程式上是否要進行安全檢查。
LDAP(Lightweight Directory Acess Protocol)是目錄服務在TCP/IP上的實作(RFC 1777 V2版和RFC 2251
V3版)。它是對X500的目錄協定的移植,但是簡化了實作方法,是以稱為輕量級的目錄服務。在LDAP中目錄是按照
樹型結構組織,目錄由條目(Entry)組成,條目相當于關系資料庫中表的記錄;條目是具有差別名DN(Distinguished
Name)的屬性(Attribute)集合,DN相當于關系資料庫表中的關鍵字(Primary
Key);屬性由類型(Type)和多個值(Values)組成,相當于關系資料庫中的域(Field)由域名和資料類型組成,
隻是為了友善檢索的需要,LDAP中的Type可以有多個Value,而不是關系資料庫中為降低資料的備援性要求實作的各
個域必須是不相關的。LDAP中條目的組織一般按照地理位置群組織關系進行組織,非常的直覺。LDAP把資料存放在
檔案中,為提高效率可以使用基于索引的檔案資料庫,而不是關系資料庫。LDAP協定集還規定了DN的命名方法、存
取控制方法、搜尋格式、複制方法、URL格式、開發接口等
LDAP對于這樣存儲這樣的資訊最為有用,也就是資料需要從不同的地點讀取,但是不需要經常更新。
例如,這些資訊存儲在LDAP目錄中是十分有效的:
l 公司員工的電話号碼簿群組織結構圖
l 客戶的聯系資訊
l 計算機管理需要的資訊,包括NIS映射、email假名,等等
l 軟體包的配置資訊
l 公用證書和安全密匙
什麼時候該用LDAP存儲資料
大多數的LDAP伺服器都為讀密集型的操作進行專門的優化。是以,當從LDAP伺服器中讀取資料的時候會比從專門為
OLTP優化的關系型資料庫中讀取資料快一個數量級。也是因為專門為讀的性能進行優化,大多數的LDAP目錄伺服器
并不适合存儲需要需要經常改變的資料。例如,用LDAP伺服器來存儲電話号碼是一個很好的選擇,但是它不能作為
電子商務站點的資料庫伺服器。
如果下面每一個問題的答案都是“是”,那麼把資料存在LDAP中就是一個好主意。
l 需要在任何平台上都能讀取資料嗎?
l 每一個單獨的記錄項是不是每一天都隻有很少的改變?
l 可以把資料存在平面資料庫(flat database)而不是關系型資料庫中嗎?換句話來說,也就是不管什麼範式不
範式的,把所有東西都存在一個記錄中(差不多隻要滿足第一範式)。
最後一個問題可能會唬住一些人,其實用平面資料庫去存儲一些關系型的資料也是很一般的。例如,一條公司員工
的記錄就可以包含經理的登入名。用LDAP來存儲這類資訊是很友善的。一個簡單的判斷方法:如果可以把保資料存
在一張張的卡片裡,就可以很容易地把它存在LDAP目錄裡。
安全和通路控制
LDAP提供很複雜的不同層次的通路控制或者ACI。因這些通路可以在伺服器端控制,這比用用戶端的軟體保證資料的
安全可安全多了。
用LDAP的ACI,可以完成:
l 給予使用者改變他們自己的電話号碼和家庭位址的權限,但是限制他們對其它資料(如,職務名稱,經理的登入名,
等等)隻有“隻讀”權限。
l 給予“HR-admins"組中的所有人權限以改變下面這些使用者的資訊:經理、工作名稱、員工号、部門名稱和部門号。
但是對其它域沒有寫權限。
l 禁止任何人查詢LDAP伺服器上的使用者密碼,但是可以允許使用者改變他或她自己的密碼。
l 給予經理通路他們上級的家庭電話的隻讀權限,但是禁止其他人有這個權限。
l 給予“host-admins"組中的任何人建立、删除和編輯所有儲存在LDAP伺服器中的與計算機主機有關的資訊
l 通過Web,允許“foobar-sales"組中的成員有選擇地給予或禁止他們自己讀取一部分客戶聯系資料的讀權限。這
将允許他們把客戶聯系資訊下載下傳到本地的筆記本電腦或個人數字助理(PDA)上。(如果銷售人員的軟體都支援LDAP,
這将非常有用)
l 通過Web,允許組的所有者删除或添加他們擁有的組的成員。例如:可以允許銷售經理給予或禁止銷售人員改變Web
頁的權限。也可以允許郵件假名(mail aliase)的所有者不經過IT技術人員就直接從郵件假名中删除或添加使用者。
“公用”的郵件清單應該允許使用者從郵件假名中添加或删除自己(但是隻能是自己)。也可以對IP位址或主機名加以
限制。例如,某些域隻允許使用者IP位址以192.168.200.*開頭的有讀的權限,或者使用者反向查找DNS得到的主機名必須
為*.foobar.com。
LDAP目錄樹的結構
LDAP目錄以樹狀的層次結構來存儲資料。如果你對自頂向下的DNS樹或UNIX檔案的目錄樹比較熟悉,也就很容易掌握
LDAP目錄樹這個概念了。就象DNS的主機名那樣,LDAP目錄記錄的辨別名(Distinguished Name,簡稱DN)是用來讀取
單個記錄,以及回溯到樹的頂部。後面會做詳細地介紹。
為什麼要用層次結構來組織資料呢?原因是多方面的。下面是可能遇到的一些情況:
l 如果你想把所有的美國客戶的聯系資訊都“推”到位于到西雅圖辦公室(負責營銷)的LDAP伺服器上,但是你不想
把公司的資産管理資訊“推”到那裡。
l 你可能想根據目錄樹的結構給予不同的員工組不同的權限。在下面的例子裡,資産管理組對“asset-mgmt"部分有完
全的通路權限,但是不能通路其它地方。
l 把LDAP存儲和複制功能結合起來,可以定制目錄樹的結構以降低對WAN帶寬的要求。位于西雅圖的營銷辦公室需要每
分鐘更新的美國銷售狀況的資訊,但是歐洲的銷售情況就隻要每小時更新一次就行了。
刨根問底:基準DN
LDAP目錄樹的最頂部就是根,也就是所謂的“基準DN"。基準DN通常使用下面列出的三種格式之一。假定我在名為FooBar
的電子商務公司工作,這家公司在Internet上的名字是foobar.com。
o="FooBar, Inc.", c=US
(以X.500格式表示的基準DN)
在這個例子中,o=FooBar, Inc. 表示組織名,在這裡就是公司名的同義詞。c=US 表示公司的總部在美國。以前,一般
都用這種方式來表示基準DN。但是事物總是在不斷變化的,現在所有的公司都已經(或計劃)上Internet上。随着
Internet的全球化,在基準DN中使用國家代碼很容易讓人産生混淆。現在,X.500格式發展成下面列出的兩種格式。
o=foobar.com
(用公司的Internet位址表示的基準DN)
這種格式很直覺,用公司的域名作為基準DN。這也是現在最常用的格式。
dc=foobar, dc=com
(用DNS域名的不同部分組成的基準DN)
就象上面那一種格式,這種格式也是以DNS域名為基礎的,但是上面那種格式不改變域名(也就更易讀),而這種格式
把域名:foobar.com分成兩部分 dc=foobar, dc=com。在理論上,這種格式可能會更靈活一點,但是對于最終使用者來說
也更難記憶一點。考慮一下foobar.com這個例子。當foobar.com和gizmo.com合并之後,可以簡單的把“dc=com"當作基
準DN。把新的記錄放到已經存在的dc=gizmo, dc=com目錄下,這樣就簡化了很多工作(當然,如果foobar.com和wocket.edu
合并,這個方法就不能用了)。如果LDAP伺服器是新安裝的,我建議你使用這種格式。再請注意一下,如果你打算使用活動
目錄(Actrive Directory),Microsoft已經限制你必須使用這種格式。
更上一層樓:在目錄樹中怎麼組織資料
在UNIX檔案系統中,最頂層是根目錄(root)。在根目錄的下面有很多的檔案和目錄。象上面介紹的那樣,LDAP目錄也是
用同樣的方法組織起來的。
在根目錄下,要把資料從邏輯上區分開。因為曆史上(X.500)的原因,大多數LDAP目錄用OU從邏輯上把資料分開來。OU
表示“Organization Unit",在X.500協定中是用來表示公司内部的機構:銷售部、财務部,等等。現在LDAP還保留ou=這
樣的命名規則,但是擴充了分類的範圍,可以分類為:ou=people, ou=groups, ou=devices,等等。更低一級的OU有時用
來做更細的歸類。例如:LDAP目錄樹(不包括單獨的記錄)可能會是這樣的:
ou=customers
ou=asia
ou=europe
ou=usa
ou=employees
ou=rooms
ou=groups
ou=assets-mgmt
ou=nisgroups
ou=recipes
單獨的LDAP記錄
DN是LDAP記錄項的名字
在LDAP目錄中的所有記錄項都有一個唯一的“Distinguished Name",也就是DN。每一個LDAP記錄項的DN是由兩個部分
組成的:相對DN(RDN)和記錄在LDAP目錄中的位置。
RDN是DN中與目錄樹的結構無關的部分。在LDAP目錄中存儲的記錄項都要有一個名字,這個名字通常存在cn(Common Name)
這個屬性裡。因為幾乎所有的東西都有一個名字,在LDAP中存儲的對象都用它們的cn值作為RDN的基礎。如果我把最喜歡的
吃燕麥粥食譜存為一個記錄,我就會用cn=Oatmeal Deluxe作為記錄項的RDN。
l 我的LDAP目錄的基準DN是dc=foobar,dc=com
l 我把自己的食譜作為LDAP的記錄項存在ou=recipes
l 我的LDAP記錄項的RDN設為cn=Oatmeal Deluxe
上面這些構成了燕麥粥食譜的LDAP記錄的完整DN。記住,DN的讀法和DNS主機名類似。下面就是完整的DN:
cn=Oatmeal Deluxe,ou=recipes,dc=foobar,dc=com
舉一個實際的例子來說明DN
現在為公司的員工設定一個DN。可以用基于cn或uid(User ID),作為典型的使用者帳号。例如,FooBar的員工Fran Smith
(登入名:fsmith)的DN可以為下面兩種格式:
uid=fsmith,ou=employees,dc=foobar,dc=com
(基于登入名)
LDAP(以及X.500)用uid表示“User ID",不要把它和UNIX的uid号混淆了。大多數公司都會給每一個員工唯一的登入名,
是以用這個辦法可以很好地儲存員工的資訊。你不用擔心以後還會有一個叫Fran Smith的加入公司,如果Fran改變了她的
名字(結婚?離婚?或宗教原因?),也用不着改變LDAP記錄項的DN。
cn=Fran Smith,ou=employees,dc=foobar,dc=com
(基于姓名)
可以看到這種格式使用了Common Name(CN)。可以把Common Name當成一個人的全名。這種格式有一個很明顯的缺點就是:
如果名字改變了,LDAP的記錄就要從一個DN轉移到另一個DN。但是,我們應該盡可能地避免改變一個記錄項的DN。
定制目錄的對象類型
你可以用LDAP存儲各種類型的資料對象,隻要這些對象可以用屬性來表示,下面這些是可以在LDAP中存儲的一些資訊:
l 員工資訊:員工的姓名、登入名、密碼、員工号、他的經理的登入名,郵件伺服器,等等。
l 物品跟蹤資訊:計算機名、IP位址、标簽、型号、所在位置,等等。
l 客戶聯系清單:客戶的公司名、主要聯系人的電話、傳真和電子郵件,等等。
l 會議廳資訊:會議廳的名字、位置、可以坐多少人、電話号碼、是否有投影機。
l 食譜資訊:菜的名字、配料、烹調方法以及準備方法。
因為LDAP目錄可以定制成存儲任何文本或二進制資料,到底存什麼要由你自己決定。LDAP目錄用對象類型
(object classes)的概念來定義運作哪一類的對象使用什麼屬性。在幾乎所有的LDAP伺服器中,你都要根據
自己的需要擴充基本的LDAP目錄
的功能,建立新的對象類型或者擴充現存的對象類型。
LDAP目錄以一系列“屬性對”的形式來存儲記錄項,每一個記錄項包括屬性類型和屬性值(這與關系型資料庫
用行和列來存取資料有根本的不同)。下面是我存在LDAP目錄中的一部分食譜記錄:
dn: cn=Oatmeal Deluxe, ou=recipes, dc=foobar, dc=com
cn: Instant Oatmeal Deluxe
recipeCuisine: breakfast
recipeIngredient: 1 packet instant oatmeal
recipeIngredient: 1 cup water
recipeIngredient: 1 pinch salt
recipeIngredient: 1 tsp brown sugar
recipeIngredient: 1/4 apple, any type
請注意上面每一種配料都作為屬性recipeIngredient值。LDAP目錄被設計成象上面那樣為一個屬性儲存多個值的,
而不是在每一個屬性的後面用逗号把一系列值分開。
因為用這樣的方式存儲資料,是以資料庫就有很大的靈活性,不必為加入一些新的資料就重新建立表和索引。更
重要的是,LDAP目錄不必花費記憶體或硬碟空間處理“空”域,也就是說,實際上不使用可選擇的域也不會花費你
任何資源。
作為例子的一個單獨的資料項
讓我們看看下面這個例子。我們用Foobar, Inc.的員工Fran Smith的LDAP記錄。這個記錄項的格式是LDIF,用來
導入和導出LDAP目錄的記錄項。
dn: uid=fsmith, ou=employees, dc=foobar, dc=com
objectclass: person
objectclass: organizationalPerson
objectclass: inetOrgPerson
objectclass: foobarPerson
uid: fsmith
givenname: Fran
sn: Smith
cn: Fran Smith
cn: Frances Smith
telephonenumber: 510-555-1234
roomnumber: 122G
o: Foobar, Inc.
mailhost: mail.foobar.com
userpassword: {crypt}3x1231v76T89N
uidnumber: 1234
gidnumber: 1200
homedirectory: /home/fsmith
loginshell: /usr/local/bin/bash
屬性的值在儲存的時候是保留大小寫的,但是在預設情況下搜尋的時候是不區分大小寫的。某些特殊的屬性
(例如,password)在搜尋的時候需要區分大小寫。
讓我們一點一點地分析上面的記錄項。
這是Fran的LDAP記錄項的完整DN,包括在目錄樹中的完整路徑。LDAP(和X.500)使用uid(User ID),不要
把它和UNIX的uid号混淆了。
可以為任何一個對象根據需要配置設定多個對象類型。person對象類型要求cn(common name)和sn(surname)
這兩個域不能為空。persion對象類型允許有其它的可選域,包括givenname、telephonenumber,等等。
organizational Person給person加入更多的可選域,inetOrgPerson又加入更多的可選域(包括電子郵件資訊)。
最後,foobarPerson是為Foobar定制的對象類型,加入了很多定制的屬性。
以前說過了,uid表示User ID。當看到uid的時候,就在腦袋裡想一想“login"。
請注意CN有多個值。就象上面介紹的,LDAP允許某些屬性有多個值。為什麼允許有多個值呢?假定你在用
公司的LDAP伺服器查找Fran的電話号碼。你可能隻知道她的名字叫Fran,但是對人力資源處的人來說她的
正式名字叫做Frances。因為儲存了她的兩個名字,是以用任何一個名字檢索都可以找到Fran的電話号碼、
電子郵件和辦公房間号,等等。
就象現在大多數的公司都上網了,Foobar用Sendmail發送郵件和處理外部郵件路由資訊。Foobar把所有使用者
的郵件資訊都存在LDAP中。最新版本的Sendmail支援這項功能。
Userpassword: {crypt}3x1231v76T89N
gecos: Frances Smith
注意,Foobar的系統管理者把所有使用者的密碼映射資訊也都存在LDAP中。FoobarPerson類型的對象具有這
種能力。再注意一下,使用者密碼是用UNIX的密碼加密格式存儲的。UNIX的uid在這裡為uidnumber。提醒你一下,
關于如何在LDAP中儲存NIS資訊,有完整的一份RFC。在以後的文章中我會談一談NIS的內建。
LDAP複制
LDAP伺服器可以使用基于“推”或者“拉”的技術,用簡單或基于安全證書的安全驗證,複制一部分或者所
有的資料。
例如,Foobar有一個“公用的”LDAP伺服器,位址為ldap.foobar.com,端口為389。Netscape Communicator
的電子郵件查詢功能、UNIX的“ph"指令要用到這個伺服器,使用者也可以在任何地方查詢這個伺服器上的員工
和客戶聯系資訊。公司的主LDAP伺服器運作在相同的計算機上,不過端口号是1389。
你可能即不想讓員工查詢資産管理或食譜的資訊,又不想讓資訊技術人員看到整個公司的LDAP目錄。為了解決
這個問題,Foobar有選擇地把子目錄樹從主LDAP伺服器複制到“公用”LDAP伺服器上,不複制需要隐藏的資訊。
為了保持資料始終是最新的,主目錄伺服器被設定成即時“推”同步。這些種方法主要是為了友善,而不是安全,
因為如果有權限的使用者想查詢所有的資料,可以用另一個LDAP端口。
假定Foobar通過從奧克蘭到歐洲的低帶寬資料的連接配接用LDAP管理客戶聯系資訊。可以建立從ldap.foobar.com:1389
到munich-ldap.foobar.com:389的資料複制,象下面這樣:
periodic pull: ou=asia,ou=customers,o=sendmail.com
periodic pull: ou=us,ou=customers,o=sendmail.com
immediate push: ou=europe,ou=customers,o=sendmail.com
“拉”連接配接每15分鐘同步一次,在上面假定的情況下足夠了。“推”連接配接保證任何歐洲的聯系資訊發生了變化就
立即被“推”到Munich。
用上面的複制模式,使用者為了通路資料需要連接配接到哪一台伺服器呢?在Munich的使用者可以簡單地連接配接到本地服務
器。如果他們改變了資料,本地的LDAP伺服器就會把這些變化傳到主LDAP伺服器。然後,主LDAP伺服器把這些變化
“推”回本地的“公用”LDAP伺服器保持資料的同步。這對本地的使用者有很大的好處,因為所有的查詢(大多數是讀)都在本地的伺服器上進行,速度非常快。當需要改變資訊的時候,最終使用者不需要重新配置用戶端的軟體,因為LDAP目錄伺服器為他們完成了所有的資料交換工作。