LDAP應(yīng)用技術(shù)簡述(轉(zhuǎn)) |
LDAP應(yīng)用技術(shù)簡述 作者:fredeirck@ www. (2005-05-12 14:54:03)
一、簡介;
a) X500目錄服務(wù); OSL X.500目錄是基于OSI網(wǎng)絡(luò)協(xié)議的目錄服務(wù)協(xié)議,也是LDAP的前身。但是X。500的缺點(diǎn)是不支持TCP/IP,而是支持OSI協(xié)議,顯然,在 Windows等個(gè)人電腦上不可以使用OSI協(xié)議,在此前提下,也就產(chǎn)生了訪問X500目錄的網(wǎng)關(guān)--LDAP。 b) LDAP; LDAP(Lightweight Directory Access Protocal, 輕型目錄訪問協(xié)議),是針對(duì)以X500目錄為主的目錄服務(wù)的前端訪問協(xié)議,是OSL X.500目錄訪問網(wǎng)關(guān)。由于X500原來不是為TCP/IP網(wǎng)絡(luò)設(shè)計(jì)的,而目錄服務(wù)的最大使用者偏偏是TCP/IP客戶,因此,LDAP就被設(shè)計(jì)成使用 TCP/IP訪問OSI 目錄服務(wù)的服務(wù)協(xié)議,而隨著互聯(lián)網(wǎng)成為網(wǎng)絡(luò)的主流,LDAP也成為一個(gè)具備目錄的大部分服務(wù)的協(xié)議。 LDAP主要解決目錄服務(wù)的前端訪問形式,而不是對(duì)目錄服務(wù)本身制定的的協(xié)議,理論上,LDAP支持后臺(tái)的任何存儲(chǔ)形式,包括X500,關(guān)系數(shù)據(jù)庫,文本數(shù)據(jù)庫或文件目錄等。LDAP繼承了X500目錄的大部分定義,無論是訪問樣式還是語法都與X500相似。
c) Active Directory 活動(dòng)目錄; Active Directory (AD)是微軟為.net中的對(duì)象訪問定義的目錄服務(wù),包括目錄服務(wù)本身,以及客戶端API(ADSI)。Ad并不是LDAP在.net中的實(shí)現(xiàn),而是 X500在.net中的實(shí)現(xiàn),但AD前端支持并主要以LDAP形式進(jìn)行訪問。完整地說,AD是基于微軟自身定義的X500擴(kuò)展的一系列Schema實(shí)現(xiàn)的 X500目錄服務(wù)及相關(guān)的訪問控制工具的集合,其前端支持LDAP的查詢,目的是對(duì).net中涉及的所有網(wǎng)絡(luò)對(duì)象提供目錄服務(wù)。各個(gè)schema在一個(gè)樹森林中是唯一的。 普通的LDAP客戶端工具與AD并不兼容。WINDOWS2000自帶有一些LDAP客戶端工具,包括ldifde.exe, ldp.exe。并提供專門的LDAP程序接口ASDI。同時(shí),可以在WINDOWS管理臺(tái)上添加AD管理snap-in,配合已有的AD基本管理工作。使用以上工具可以得到微軟樣式的詳情,但總的來說,WINDOWS2000原則上不鼓勵(lì)用戶在AD的基礎(chǔ)上進(jìn)一步的開發(fā),沒有開發(fā)更多的資料。 WINDOWS2000中,訪問AD記錄的API被集成到了內(nèi)核,服務(wù)于WINDOWS2000從主機(jī)權(quán)限和對(duì)象管理,直接網(wǎng)絡(luò)的權(quán)限和對(duì)象管理,同時(shí)API細(xì)節(jié)沒有對(duì)外公開。因此,某種程度上,AD是一個(gè)只對(duì)WINDOWS2000有用的目錄服務(wù),AD連同訪問API,形成一個(gè)基于 X500-LDAP的孤島,從一開始就沒有打算與其他廠商產(chǎn)品有兼容的余地,這也是微軟的一貫風(fēng)格。參考: http://www.microsoft.com/windows2000/en/server/help/default.asp? url=/windows2000/en/server/help/sag_ADschema_Intro.htm http://msdn.microsoft.com/library/default.asp? url=/library/en-us/netdir/ad/schema_implementation.asp
AD在WINDOWS2000中注冊表中的位置是:HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\NTDS\ 使用AD時(shí),用戶可以自行在微軟樣式的基礎(chǔ)上添加新的類和屬性,微軟稱這個(gè)就是schema的增添,這與UNIX環(huán)境下有一些不同,用戶余地較少。如果真的需要添加,可以使用按:http://www.microsoft.com/ windows2000/techinfo/planning/activedirectory/adschemasteps.asp 的指示一步步做,也可以預(yù)先做好ldif文件,使用ldifde.exe一次性地進(jìn)行添加,效果是一樣的。 在默認(rèn)的狀況下,WINDOWS2000的AD初始具備三個(gè)上下文對(duì)象: dc=domainname; 微軟定義domainname必須是examples.com格式,即dc=example,dc=com; cn=Configuration,dc=example,dc=com; 這一條目和上下文存儲(chǔ)設(shè)置信息; cn=schema,cn=configuration,dc=example,dc=com;
二、服務(wù)器實(shí)現(xiàn)方式; 用戶可以選擇購買商業(yè)的LDAP服務(wù)器,如SUN的iplanet directory server;但在大部分情況下,使用openldap足以完成所需要的目錄服務(wù)工作。另外,包括windows 2000以及如domino6這樣的系統(tǒng)軟件中,通常也都集成了一個(gè)自身使用的LDAP服務(wù)器。
三、數(shù)據(jù)結(jié)構(gòu)原理;
不少LDAP開發(fā)人員喜歡把LDAP與關(guān)系數(shù)據(jù)庫相比,認(rèn)為是另一種的存貯方式,然后在讀性能上進(jìn)行比較。實(shí)際上,這種對(duì)比的基礎(chǔ)是錯(cuò)誤的。LDAP和關(guān)系數(shù)據(jù)庫是兩種不同層次的概念,后者是存貯方式(同一層次如網(wǎng)格數(shù)據(jù)庫,對(duì)象數(shù)據(jù)庫),前者是存貯模式和訪問協(xié)議。LDAP是一個(gè)比關(guān)系數(shù)據(jù)庫抽象層次更高的存貯概念,與關(guān)系數(shù)據(jù)庫的查詢語言SQL屬同一級(jí)別。 LDAP是實(shí)現(xiàn)了指定的數(shù)據(jù)結(jié)構(gòu)的存貯,它包括以下可以用關(guān)系數(shù)據(jù)庫實(shí)現(xiàn)的結(jié)構(gòu)要求:樹狀組織、條目認(rèn)證、類型定義、許可樹形記錄拷貝。 a) 樹狀組織; 無論是X500還是LDAP都是采用樹狀方式進(jìn)行記錄。每一個(gè)樹目錄都有一個(gè)樹根的入口條目,子記錄全部是這一根條目的子孫。這是目錄與關(guān)系數(shù)據(jù)類型最大的區(qū)別(關(guān)系數(shù)據(jù)庫的應(yīng)用結(jié)構(gòu)也可實(shí)現(xiàn)樹狀記錄)。因此,把目錄看作是更高級(jí)的樹狀數(shù)據(jù)庫也未嘗不可,只不過除此外,它不能實(shí)現(xiàn)關(guān)系存貯的重要功能。
b) 條目和條目認(rèn)證; LDAP是以條目作為認(rèn)證的根據(jù)。ROOT的權(quán)限認(rèn)證與目錄本身無關(guān),但除此外所有條目的認(rèn)證權(quán)限由條目本身的密碼進(jìn)行認(rèn)證。LDAP可以配置成各種各樣不同的父子條目權(quán)限繼承方式。 每一個(gè)條目相當(dāng)于一個(gè)單一的平面文本記錄,由條目自身或指定的條目認(rèn)證進(jìn)行訪問控制。因此,LDAP定義的存貯結(jié)構(gòu)等同于一批樹狀組織的平面數(shù)據(jù)庫,并提供相應(yīng)的訪問控制。 條目中的記錄以名-值對(duì)的形式存在,每一個(gè)名值對(duì)必須由數(shù)據(jù)樣式schema預(yù)定義。因此,LDAP可以看作是以規(guī)定的值類型以名值對(duì)形式存貯在一系列以樹狀組織的平面數(shù)據(jù)庫的記錄的集合。 c) 數(shù)據(jù)樣式(schema); 數(shù)據(jù)樣式schema是針對(duì)不同的應(yīng)用,由用戶指定(設(shè)計(jì))類和屬性類型預(yù)定義,條目中的類(objectclass)和屬性必須在在 LDAP服務(wù)器啟動(dòng)時(shí)載入內(nèi)存的schema已有定義。因此,AD活動(dòng)目錄中的條目記錄就必須符合Active Directory的schema中。如果已提供的schema中的定義不夠用,用戶可以自行定義新的schema. 在這里 中可以看到常用的schema。
d) 類型分類(objectClass); 條目中的記錄通過objectclass實(shí)現(xiàn)分類,objectClass是一個(gè)繼承性的類定義,每一個(gè)類定義指定必須具備的屬性。如某一條目指定必須符合unit類型,則它必須具備chinacfirm類形指定的屬性,象法人代表什么的。 通過objectclass分類,分散的條目中的記錄就實(shí)際上建立了一個(gè)索引結(jié)構(gòu),為高速的讀查詢打下了基礎(chǔ)。Objectclass也是過濾器的主要查詢對(duì)象。
e) 過濾器和語法; LDAP是一個(gè)查詢?yōu)橹鞯挠涗浗Y(jié)構(gòu),無論是何種查詢方式,最終都由過濾器缺點(diǎn)查詢的條件。過濾器相當(dāng)于SQL中的WHERE子句。任何LDAP的類過濾和字符串都必須放在括號(hào)內(nèi),如(objectclass=*),指列出所有類型的記錄(不過分類)。 可以使用=,>=,<=,~=(約等于)進(jìn)行比較,如(number<=100)。合并條件是最怪的,必須把操作符放在兩個(gè)操作對(duì)象的前面而不是中間,單一操作對(duì)象用括號(hào)括起來。如 A與B,不是A&B,而是(&(A)(B))。 或使用"|"表示; 非使用"!"表示。 對(duì)于"與",或"或"在操作符后可以跟多個(gè)條件表達(dá)式,但非后則只參是單個(gè)表達(dá)式。 詳見RFC1558。
f) 樹移植; LDAP最重要的特性和要求并不是讀性能,而是擴(kuò)展性。這一特性是通過樹移植和樹復(fù)制實(shí)現(xiàn)的。按LDAP的RFC要求,LDAP目錄應(yīng)該可以任意地在不同的目錄間連接、合并并實(shí)現(xiàn)自動(dòng)復(fù)制,及自動(dòng)性同步。這意味著用戶可以在任一LDAP中訪問條目,而不用管其中某一部分是否復(fù)制自全世界另一目錄中的記錄,同時(shí)另一目錄中的記錄同樣在正常運(yùn)作。 這一特性如果在關(guān)系數(shù)據(jù)庫中實(shí)現(xiàn),意味著要使用程序化的非規(guī)范化預(yù)復(fù)制。類似于匯總帳目的設(shè)計(jì)。 g) LDIF交換文件 LDIF是LDAP約定的記錄交換格式,以平面文本的形式存在,是大部分LDAP內(nèi)容交換的基礎(chǔ),如拷貝、添加、修改等操作,都是基于LDIF文件進(jìn)行操作。
f) JAVA或CORBA對(duì)象串行化存儲(chǔ) 網(wǎng)絡(luò)高效率的訪問加上JAVA的跨平臺(tái)能力,當(dāng)把JAVA或CORBA對(duì)象串行化后存儲(chǔ)到LDAP目錄上時(shí),可以產(chǎn)生非同一般的集成效果--實(shí)際上,這正是EJB和.NET的網(wǎng)絡(luò)定位基礎(chǔ)技術(shù)。 使用JAVA或CORBA對(duì)象存儲(chǔ)時(shí),必須首先讓LDAP服務(wù)支持該對(duì)象定義,也就是說包含qmail.schema或corba.schema。 JAVA必須存儲(chǔ)在objectclass=javacontainer的條目中,而且必須帶有cn屬性,這意味著除非該JAVA類專門實(shí)現(xiàn)了DirContext接口,對(duì)于大多數(shù)JAVA類來說,只能采用DirContext代替Context實(shí)現(xiàn)bind的添加操作。取出JAVA類相對(duì)要簡單得多,只需使用context.lookup()獲得該對(duì)象的句柄,然后強(qiáng)制造型成所需要的對(duì)象就可以了,如: Person p=(Person)contex.lookup("cn=elvis,dc=daifu,dc=com"); 這個(gè)句法在EJB的程序中,是經(jīng)常用到的。 使用CORBA的跨語言性質(zhì),使用CORBA存儲(chǔ)對(duì)象比JAVA更加誘人,這意味著所存儲(chǔ)的對(duì)象可以被任何語言編寫的客戶端訪問。其實(shí),微軟的.net說到底也非常簡單,無非是把COM對(duì)象存儲(chǔ)到微軟自家的目錄ActiveDirectory里面,從而可以在網(wǎng)絡(luò)范圍內(nèi)使用任何微軟平臺(tái)的語言進(jìn)行對(duì)象訪問而已。眾所周知,COM就是與CORBA相對(duì)的微軟規(guī)范。 使用對(duì)象串行化技術(shù),可以把常用對(duì)象如某個(gè)打印機(jī),某個(gè)客戶直接存儲(chǔ)到LDAP中,然后快速獲取該對(duì)象的引用,這樣,就比把對(duì)象信息存儲(chǔ)到關(guān)系數(shù)據(jù)庫中,分別取出屬性,然后再初始化對(duì)象操作的做法,效率要高得多了。這是LDAP目前比普通關(guān)系數(shù)據(jù)庫存儲(chǔ)要優(yōu)秀的地方,而對(duì)象數(shù)據(jù)庫還不成熟。
客戶端訪問工具;
a) openldap命令行;
Openldap提供了在UNIX命令行下的訪問工具集。包括ldapsearch,ldapadd,ldapmodify,ldappassword,ldapdelete等必要的工具。除了使用man獲得使用幫助外,還可以在http://www./HOWTO/LDAP-HOWTO/,及http://www.csis./GeneralInfo/Oracle/network.920/a96579/,獲得使用的支持。
例子:通過查詢根上下文判斷LDAP服務(wù)器是否正常工作:
$ ldapsearch -x -b "" -s base "objectclass=*" namingContexts
注:該命令查詢該當(dāng)前服務(wù)器上的命令上下文,通常就是rootdn的上下文記錄。
-x 指該查詢使用目錄認(rèn)證而不是使用SASL認(rèn)證,;
-b “” 是查詢的起點(diǎn),即base,空指從根開始查詢;
-s base 指查詢范圍。有三種選項(xiàng),one指一層,包括兄弟條目;base指當(dāng)前條目,sub,子孫記錄。默認(rèn)是sub.
“objectclass=*” 是過濾器,表示所有記錄類型都加以選擇;
namingContexts是約定的特殊屬性,可以選擇其他屬性值進(jìn)行查詢。
$ ldapsearch -x -b "dc=daifu,dc=com" -s base "objectclass=organization" dn dc
注:
-b “dc=daifu,dc=com” 指查詢的是“dc=daifu,dc=com”的條目,需要注意的是,slapd.conf中指定rootdn為“dc=daifu,dc=com”,并不等同于目錄中已經(jīng)具有真實(shí)的“dc=daifu,dc=com”條目。
"objectclass=organization" 指查詢條件是organization類的。
“dc dc”指只需列出dn,dc兩項(xiàng)屬性。
(ldapadd),ldapmodify的操作是基于LDIF文件的,所以必須先按規(guī)則生成LDIF文本文件,然后執(zhí)行導(dǎo)入。要注意的是,新裝的LDAP具備一個(gè)上下文,并不等于在目錄中有相應(yīng)的條目。如,OPENLDAP的slapd.conf中已經(jīng)定義了一個(gè)根“dc=daifu,dc=com”,并不等于可以把新的條目添加到”dc=daifu,dc=com”,因此實(shí)際上并沒有這一條目,必須先執(zhí)行添加相應(yīng)的條目,然后才可以添加后續(xù)條目。
其次,LDIF的格式文件非常嚴(yán)格,空間被認(rèn)為是確定的字符,因此,需要特別注意每行后面不應(yīng)帶有空格。
b) ldapbrowser;
ldapbrowser是開源的LDAP瀏覽工具,并帶有不太強(qiáng)的條目編輯功能。Ldapbrowser是純JAVA的程序,可跨平臺(tái)運(yùn)行,在開源的程序中,是最優(yōu)秀的一個(gè)。缺點(diǎn)是不能瀏覽服務(wù)器端的schema對(duì)象,從而限制了條目編輯(添加)的能力。
其次,由于JAVA對(duì)LDAP的訪問方式在添加時(shí),必須預(yù)先生成一個(gè)實(shí)現(xiàn)DirContext接口的類,因此,這也令訂制型的添加操作在JAVA實(shí)現(xiàn)時(shí)相當(dāng)困難。
c) ldapadministrator;
ldapadministrator是一個(gè)windows的收費(fèi)程序,試用一個(gè)月。Ldapadministrator除了具備ldapbrowser的功能外,在條目編輯上的功能大為增強(qiáng)。
但從另一個(gè)角度看,LDAP總是涉及到大量的條目,當(dāng)需要編輯的條目急速增加時(shí),使用ldapadminstrator就不是輕松的事情,此時(shí)還是使用LDIF文件交 換為佳。
d) 瀏覽器;
根據(jù)rfc2255.txt的約定,可以使用URI定義LDAP查詢,因此,理論上,只要瀏覽器內(nèi)嵌支持,就可以作為LDAP客戶端使用。 IE瀏覽器支持簡單的LDAP查詢。此時(shí),IE把LDAP的URI看作是查詢的對(duì)象。但是IE以及Exchange server非常狹隘地把LDAP看作是純粹為EMAIL地址查詢服務(wù)的,只能以“圖形”的方式顯示查到的郵件地址什么的。因此,IE準(zhǔn)確地說,是對(duì)LDAP存儲(chǔ)的郵件地址信息的查詢工具。
URI查詢語法是: ldapurl = scheme "://" [hostport] ["/" [dn ["?" [attributes] ["?" [scope] ["?" [filter] ["?" extensions]]]]]] scheme = "ldap" attributes = attrdesc *("," attrdesc) scope = "base" / "one" / "sub" dn = distinguishedName from Section 3 of [1] hostport = hostport from Section 5 of RFC 1738 [5] attrdesc = AttributeDeion from Section 4.1.5 of [2] filter = filter from Section 4 of [4] extensions = extension *("," extension) extension = ["!"] extype ["=" ex] extype = token / xtoken ex = LDAPString from section 4.1.2 of [2] token = oid from section 4.1 of [3] xtoken = ("X-" / "x-") token
例:
類似
#ldapsearch –x –h 192.168.0.2 –p 389 -b “dc=daifu,dc=com” –b “sub” “objectclass=qmailuser”
的URI查詢是:
ldap://192.168.0.2:389/dc=daifu,dc=com??sub?objectclass=qmailuser?
瀏覽器并不是完全的LDAP客戶工具。
e) ldapexplorer(PHP)
一個(gè)用PHP寫的LDAP處理工具
二、 編寫LDAP訪問程序;
a) JAVA
i. JNDI(JAVA 命名及目錄接口)
JNDI是JAVA為命名及目錄服務(wù)訪問制定的基礎(chǔ)接口標(biāo)準(zhǔn),用于訪問包括DNS,NIS,LDAP,文件系統(tǒng)等任何以樹目錄形式存在目標(biāo)對(duì)象,并且基本上可保持訪問方式的一致(意味著代碼共用)。對(duì)于不同的目錄類型,JNDI通過使用不同的目錄驅(qū)動(dòng),以保證訪問方式的一致。
以下連接可獲得較詳細(xì)的講解和例程:http://java./products/jndi/tutorial/
經(jīng)常使用的LDAP驅(qū)動(dòng)有JDK自帶的LDAP provider,還有IBM的PROVIDER,以及NOVEL的JNDI產(chǎn)品。需要提醒的是,JNDI中最重要的概念是上下文context,即定位從那一個(gè)入口開始操作,相當(dāng)于openldap命令行中的-D開關(guān)的作用。其他的操作都是該上下文對(duì)象的調(diào)用。
LDAP通過JNDI添加條目是基于DirContext類的操作。由于JAVA只能以對(duì)象方式向LDAP添加條目,因此,必須首先具備實(shí)現(xiàn)DirContext接口的類,或使用DirContext(擴(kuò)充了context接口)代替context,然后才能通過ctx.bind()的方法把該類添加到目錄中。
JAVA-LDAP-ADD的操作可以有三種方式:
Context.bind()或ctx.createSubcontext("name");
或DirContext.bind(“dn”,attrs,object)的方式。對(duì)于沒有預(yù)先編寫實(shí)現(xiàn)DirContext接口的類對(duì)象的添加,這是唯一的辦法。
ii. JLDAP
JLDAP是由novel開發(fā)的,原是針對(duì)Novel的NDS目錄設(shè)計(jì)的JAVA訪問工具。NOVEL的NDS和網(wǎng)景(NETSCAPE)的目錄是工具界最早的目錄產(chǎn)品。JLDAP并非JNDI的服務(wù)供應(yīng)者,而是同一抽象層次下的訪問工具集。與JNDI-LDAP相比,JLDAP更接近于類關(guān)系數(shù)據(jù)庫的訪問方式。
NDS是遵守LDAP協(xié)議的并進(jìn)行了擴(kuò)展的類MAD產(chǎn)品。而NOVEL也已把JLDAP捐獻(xiàn)給了OPENLDAP開源項(xiàng)目,可以世界范圍內(nèi)自由使用。與JNDI相比,JLDAP無須繼承DirContext才能實(shí)現(xiàn)添加,也無需預(yù)先生成添加的類,可以象普通數(shù)據(jù)訪問那樣,生成連接,然后使用::add方法添加。這樣,添加的靈活性要強(qiáng)于JNDI。
但由于JLDAP目前是訪問NDS,因此,它不具備JNDI完全面向?qū)ο蟠鎯?chǔ)的能力,對(duì)于高級(jí)的LDAP應(yīng)用,JLDAP不是合適的選擇。
例:
import com.novell.ldap.*;
public class AddEntry
{
public static void main( String[] args )
{
if (args.length != 4) {
System.err.println("Usage: java AddEntry <host name> <login dn>"
+ " <password> <container>");
System.err.println("Example: java AddEntry Acme.com"
+ " \"cn=admin,o=Acme\" secret \"ou=Sales,o=Acme\"");
System.exit(1);
}
int ldapPort = LDAPConnection.DEFAULT_PORT;
int ldapVersion = LDAPConnection.LDAP_V3;
String ldapHost = args[0];
String loginDN = args[1];
String password = args[2];
String containerName = args[3];
LDAPConnection lc = new LDAPConnection();
LDAPAttribute attribute = null;
LDAPAttributeSet attributeSet = new LDAPAttributeSet();
/* To Add an entry to the directory,
* -- Create the attributes of the entry and add them to an attribute set
* -- Specify the DN of the entry to be created
* -- Create an LDAPEntry object with the DN and the attribute set
* -- Call the LDAPConnection add method to add it to the directory
*/
String objectclass_s[] = { "inetOrgPerson" };
attribute = new LDAPAttribute( "objectclass", objectclass_s );
attributeSet.add( attribute );
String cn_s[] = { "James Smith", "Jim Smith", "Jimmy Smith" };
attribute = new LDAPAttribute( "cn", cn_s );
attributeSet.add( attribute );
String givenname_s[] = { "James", "Jim", "Jimmy" };
attribute = new LDAPAttribute( "givenname", givenname_s );
attributeSet.add( attribute );
attributeSet.add( new LDAPAttribute( "sn", "Smith" ) );
attributeSet.add( new LDAPAttribute( "telephonenumber",
"1 801 555 1212" ) );
attributeSet.add( new LDAPAttribute( "mail", "JSmith@Acme.com" ) );
String dn = "cn=JSmith," + containerName;
LDAPEntry newEntry = new LDAPEntry( dn, attributeSet );
try {
// connect to the server
lc.connect( ldapHost, ldapPort );
// authenticate to the server
lc.bind( ldapVersion, loginDN, password );
lc.add( newEntry );
System.out.println( "\nAdded object: " + dn + " successfully." );
// disconnect with the server
lc.disconnect();
}
catch( LDAPException e ) {
System.out.println( "Error: " + e.toString());
}
System.exit(0);
}
}
iii. JdbcLDAP
JDBCLDAP是OcterString提供的,能過類SQL實(shí)現(xiàn)LDAP訪問的工具。JDBCLDAP是針對(duì)大量熟悉SQL而對(duì)LDAP欠缺了解的程序員而設(shè)計(jì)的,可以完成簡單的LDAP查詢、插入、更新、刪除這樣的工作。
JdbcLDAP使用LDAP-JDBC驅(qū)動(dòng)訪問“LDAP數(shù)據(jù)庫”:
Class.forName("com.octetstring.jdbcLdap.sql.JdbcLdapDriver");
連接時(shí)使用各個(gè)DN的具體權(quán)限建立連接:
String ldapConnectString = "jdbc:ldap://localhost:389/dc=examples,dc=com?SEARCH_SCOPE:=subTreeScope"; java.sql.Connection con; con = DriverManager.getConnection(ldapConnectString,"cn=Admin","manager");
連接字符串遵從標(biāo)準(zhǔn)的LDAP-URL格式,(RFC2255)。
SQL操作時(shí),將每一個(gè)目錄ENTRY看作是一個(gè)統(tǒng)一表的一行,然后把屬性看作列,如:
String SQL = "INSERT INTO cn,ou (objectClass,objectClass,objectClass,ou,sn,cn) " + "S (top,person,organizationalPerson,Product Development,Boorshtein," + "Marc Boorshtein)"; Statement insert = con.createStatement(); int count = insert.executeUpdate(SQL); if (count < 1) { System.out.println("Insert Failed"); } else { System.out.println("Insert Succeeded"); }
Ou,sn,cn是新條目的入口標(biāo)識(shí)。
Jdbc-LDAP不可以完成串行化binding,因此,只適宜對(duì)已有的LDAP進(jìn)行臨時(shí)訪問(如程序員不熟悉,或保持舊程序,僅修改必要的連接項(xiàng)),不宜把整個(gè)項(xiàng)目建筑在JDBC-LDAP上。實(shí)際上,LDAP本身就是一種訪問的前端協(xié)議,硬要把SQL再作為前端使用,是完全沒有必要的。
b) C語言:
包括openldap,netscape(sun),mozilla, novell,ibm等,都提供了LDAP的C SDK和接口函數(shù)。作為RFC標(biāo)準(zhǔn)的LDAP結(jié)構(gòu),struct LDAP是定義為對(duì)用戶隱藏的,并在各個(gè)實(shí)現(xiàn)函數(shù)中各自定義,以便適應(yīng)不同的LDAP訪問。
#typedef struct ldap LDAP在ldap.h中定義;在2.0版以后,struct LDAP改為隱藏,只能能過函數(shù)ldap_set_option 和ldap_get_option訪問。(draft-ldapext-ldap-c-api-xx.txt)
使用時(shí):
如:
LDAP *Ld=null; //聲明并初始化LDAP類型的變量指針 *ld;
Ld =ldap_init( ldaphost, ldapport ); //獲取LDAP的會(huì)話;
獲得會(huì)話后,調(diào)用ldap_simple_bind_s獲得訪問LDAP的權(quán)限,然后就可以調(diào)用不同的函數(shù),如
ldap_search_ext( ld, base, scope, filter, attrs, attrsonly,
sctrls, cctrls, timeout, sizelimit, &msgid );
即可完成相關(guān)的操作。
即步驟為:1。獲得會(huì)話;2。綁定對(duì)象;3。執(zhí)行操作。
連接例子:
#i nclude <stdio.h>
#i nclude "ldap.h"
/* Adjust these setting for your own LDAP server */
#define HOSTNAME "localhost"
#define PORT_NUMBERLDAP_PORT
#define FIND_DN "uid=bjensen, ou=People, o=Airius.com"
int
main( int argc, char **argv )
{
LDAP*ld;
LDAPMessage*result, *e;
BerElement*ber;
char*a;
char**vals;
int i, rc;
/* Get a handle to an LDAP connection. */
if ( (ld = ldap_init( HOSTNAME, PORT_NUMBER )) == NULL ) {
perror( "ldap_init" );
return( 1 );
}
/* Bind anonymously to the LDAP server. */
rc = ldap_simple_bind_s( ld, NULL, NULL );
if ( rc != LDAP_SUCCESS ) {
fprintf(stderr, "ldap_simple_bind_s: %s\n", ldap_err2string(rc));
return( 1 );
}
/* Search for the entry. */
if ( ( rc = ldap_search_ext_s( ld, FIND_DN, LDAP_SCOPE_BASE,
"(objectclass=*)", NULL, 0, NULL, NULL, LDAP_NO_LIMIT,
LDAP_NO_LIMIT, &result ) ) != LDAP_SUCCESS ) {
fprintf(stderr, "ldap_search_ext_s: %s\n", ldap_err2string(rc));
return( 1 );
}
/* Since we are doing a base search, there should be only
one matching entry. */
e = ldap_first_entry( ld, result );
if ( e != NULL ) {
printf( "\nFound %s:\n\n", FIND_DN );
/* Iterate through each attribute in the entry. */
for ( a = ldap_first_attribute( ld, e, &ber );
a != NULL; a = ldap_next_attribute( ld, e, ber ) ) {
/* For each attribute, print the attribute name and s. */
if ((vals = ldap_get_s( ld, e, a)) != NULL ) {
for ( i = 0; vals[i] != NULL; i++ ) {
printf( "%s: %s\n", a, vals[i] );
}
ldap__free( vals );
}
ldap_memfree( a );
}
if ( ber != NULL ) {
ber_free( ber, 0 );
}
}
ldap_msgfree( result );
ldap_unbind( ld );
return( 0 );
}
i. Novell函數(shù)庫:
Novel提供了基于普通LDAP函數(shù)庫的擴(kuò)展,主要包括兩個(gè)部分:針對(duì)Novel eDirectory服務(wù)器產(chǎn)品的擴(kuò)展,其次是對(duì)如ldapsearch等常用函數(shù)的擴(kuò)展。詳情可從:http://developer./ndk/qstart/opensource.htm#ldapc 獲得幫助;
ii. Netscape函數(shù)庫;
Netscape一度是企業(yè)級(jí)目錄服務(wù)提供者,許多LDAP的C例子,實(shí)際上都是基于Netscape服務(wù)器的。但在Netscape被收購后,其目錄服務(wù)成了iPlanet和SUN eDirectory產(chǎn)品的一部分,出于支持JAVA和iplanet產(chǎn)品的緣故,SUN對(duì)該產(chǎn)品和相關(guān)庫的支持遠(yuǎn)不夠積極,特別是對(duì)linux的支持不夠充分,估計(jì)也與保護(hù)solaris產(chǎn)品有關(guān)。
iii. Mozilla函數(shù)庫:
Mozilla可以看作是Netscape的另一個(gè)分支。準(zhǔn)確地說,Netscape本來就是源于Mozilla。Mozilla是也是一個(gè)開源的項(xiàng)目,提供完整的C-SDK,缺點(diǎn)是對(duì)linux的支持不夠充分。
c) Perl接口
Perl 的NET::LDAP模塊中包括有完整的LDAP目錄訪問函數(shù),只要安裝NET::LDAP就可以完成正常的LDAP目錄訪問;但在安裝NET::LDAP模塊前,必須先安裝Convert::ASN1模塊,該模塊可以從CPAN下載。
例:
#!/usr/bin/perl
use warnings;
use strict;
use Net::LDAP;
use Net::LDAP::Util qw(ldap_error_text);
my $server = "localhost";
my $ldap = new Net::LDAP($server) ||
die("failed to connect to server.$!\n");
my $mesg = $ldap->bind("cn=Manager,dc=daifu,dc=com", password => "secret");
die ("bind failed with ",ldap_error_text($mesg->code()),"\n")
if $mesg->code();
$mesg = $ldap->search(base => "dc=daifu,dc=com", scope => "sub",
filter => "sn=*",);
die ("search failed with ",ldap_error_text($mesg->code()),"\n")
if $mesg->code();
print "Count is ",$mesg->count(),"\n";
while (my $entry = $mesg->shift_entry()) {
print "dn:",$entry->dn(),"\n";
for my $attr($entry->attributes()) {
for my $val($entry->get_($attr)) {
print "$attr:$val\n";
}
}
print "\n";
}
操作過程實(shí)際上與C和JAVA是一樣的。
(http://www.)
原文鏈接:http://www./articles/ldap.php
|
|
|