Java命名和目錄接口(the Java naming and directory interface,JNDI)是一組在Java應用中訪問命名和目錄服務的API。命名服務將名稱和對象聯繫起來,使得讀者能夠用名稱訪問對象。目錄服務是一種命名服務,在這種服務裏,對象不但有名稱,還有屬性。前端
命名或目錄服務使讀者能夠集中存儲共有信息,這一點在網絡應用中是很是重要的,由於這使得這樣的應用更協調、更容易管理。例如,能夠將打印機設置存儲在目錄服務中,以便被與打印機有關的應用使用。java
本章將在學習瞭解JNDI的基本特色後,用代碼示例的方式詳細講解JNDI,使讀者能夠了解和使用JNDI。數據庫
在一個企業中,命名服務爲讀者的應用程序在網絡上定位對象提供了一種方法。一個命名服務將對象和名稱聯繫在了一塊兒,而且能夠經過它們指定的名稱找到相應的對象。編程
JNDI是Java命名和目錄接口,是一個爲Java應用程序提供命名服務的應用程序編程接口(API)。它爲開發人員提供了查找和訪問各類命名和目錄服務的通用、統一的接口,相似於JDBC都是構建在抽象層上。要使用JNDI,必需要安裝jdk 1.3以上版本。後端
JNDI包含了大量的命名和目錄服務,它使用通用接口來訪問不一樣種類的服務,能夠同時鏈接到多個命名或目錄服務上並創建起邏輯關聯。瀏覽器
命名服務是一種服務,它提供了爲給定的數據集建立一個標準名字的能力。它容許把名稱同Java對象或資源關聯起來,而沒必要指出對象或資源的物理ID。這相似於字典結構(或者是Java的map結構),該結構中鍵映射到值。例如在Internet上的域名服務(domain naming service,DNS)就是提供將域名映射到IP地址的命名服務,在打開網站時通常都是在瀏覽器中輸入名字,經過DNS找到相應的IP地址,而後打開。服務器
全部的因特網通訊都使用TCP、UDP或IP協議。IP地址由4個字節32位二進制數字組成,數字和名字相比,對於人來講名字比數字要容易記憶,但對於計算機來說,它更善於處理數字。網絡
其實全部的命名服務都提供DNS這種基本功能,即一個系統向命名服務註冊,命名服務提供一個值到另外一個值的映射。而後,另一個系統訪問命名服務就能夠取得映射信息。這種交互關係對分佈式企業級應用來說顯得很是重要。數據結構
在Java中,基本的名字操做包含在Context接口中。框架
目錄服務是一種特殊類型的數據庫,與SQL Server、Access、Oracle等關係數據庫管理系統相反,構造目錄服務的目的是爲了處理基於行爲的事務,而且使用一種關係信息模型。目錄服務將命名服務的概念進一步引伸爲提供具備層次結構的信息庫,這一信息庫除了包含一對一的關係外,還有信息的層次結構。對目錄服務而言,這種層次結構一般用於優化搜索操做,而且也能夠按實際狀況進行分佈或者跨網絡複製。
一個目錄服務一般擁有一個名字服務(可是一個名字服務沒必要具備一個目錄服務)。如電話簿就是一個典型的目錄服務,通常先在電話簿裏找到相關的人名,再找到這我的的電話號碼。
每一種目錄服務均可以存儲有關用戶名、用戶密碼、用戶組(若有關訪問控制的 信息)、以太網地址、IP地址等信息。它所支持的信息和操做會由於所使用的目錄服務的不一樣而不一樣。遺憾的是,訪問不一樣目錄服務的協議也會不一樣,因此讀者須要瞭解多 種API。
這就是JNDI的起源,就像JDBC同樣,JNDI充當不一樣名稱和目錄服務的通用API或者說是前端,而後使用不一樣的後端適配器來鏈接實際服務。如圖6-1顯示了JNDI和LDAP如何共同合做,爲客戶提供一種完美的解決方案。
在這裏,使用JNDI完成與LDAP服務器之間的通訊,對開發者來講他們只擔憂一個特殊協議(LDAP)和一個API(JNDI),而由開發商給他們本身的各個協議提供LDAP接口。事實上對這些流行的目錄服務中來講,都有產品可以讓開發者經過LDAP與這些目錄服務通訊。
JNDI是J2EE技術中的一個完整的組件。它支持經過一個單一的方法訪問不一樣的、新的和已經存在的服務的方法。這種支持容許任何服務提供商執行經過標準服務提供商接口(SPI)協定插入JNDI框架。另外,JNDI容許Weblogic服務器上的Java應用程序經過插入適當的服務提供者來訪問像LDAP這樣的標準化方式的外部目錄服務。
基本的目錄服務操做包含在DirContext接口中。
輕量目錄訪問協議(lightweight directory access protocol,LDAP)是在20世紀90年代早期做爲標準目錄協議進行開發的。它是目前最流行的目錄協議,與廠商跟平臺無關。
LDAP能夠追溯到X.500協議,而X.500協議最初是基於OSI網絡協議發展起來的。LDAP的第3版協議是在RFC2251中定義的,而且已經很是成熟,它的最新補充部分包含LDAP的XML規範,稱爲目錄服務標記語言。
Java語言經過使用LDAP API,如Netscape Directory 服務器能夠直接使用LDAP,或者經過JNDI來使用LDAP。JNDI是J2SE中的標準API,是通用的API,沒必要綁定到LDAP。
LDAP定義客戶應當如何訪問服務器中的數據,它並不指定數據應當如何存儲在服務器上。大多數狀況下,開發者只須要和一個專爲LDAP設計的目錄服務,或現有目錄服務的LDAP前端打交道。LDAP可以成爲任何數據存儲類型的前端。目前最流行的目錄服務有NIS、NDS、Active Directory等都有某種類型的LDAP前端。
LDAP和關係數據庫是兩種不一樣層次的概念,後者是存儲方式(同一層次如網格數據庫,對象數據庫),前者是存儲模式和訪問協議。LDAP是一個比關係數據庫抽象層次更高的存儲概念,與關係數據庫的查詢語言SQL屬於同一級別。LDAP最基本的形式是一個鏈接數據庫的標準方式,該數據庫爲讀查詢做了優化。所以它能夠很快地獲得查詢結果,不過在其餘方面,例如更新操做等就慢得多。
從另外一個意義上來說,LDAP是實現了指定的數據結構的存儲,它是一種特殊的數據庫。可是LDAP和通常的數據庫不一樣,明白這一點是很重要的。LDAP對查詢進行了優化,與寫性能相比,LDAP的讀性能要優秀不少。LDAP服務器也是用來處理查詢和更新LDAP目錄的。換句話說,LDAP目錄也是一種類型的數據庫,但不是關係型數據庫。要特別注意的是,LDAP一般做爲一個hierarchal數據庫使用,而不是一個關係數據庫。
1.LDAP數據
在LDAP中,數據被組織成一棵樹的形式,叫作目錄信息樹(directory information tree,DIT)。DIT中的第一個「葉子」叫作一個條目(entry),第一個條目叫根條目(root entry)。
一個條目是由一個區分名稱DN(distinguished name)和任意一個屬性/值對組成。DN是一個條目的名字,它必須是惟一的,它相似於一個關係型數據庫的惟一關鍵字。DN也代表了該條目與DIT樹的其餘部分之間的關係,它相似於這種方式:一個文件的全路徑名代表硬盤上的一個特定文件與系統中的其餘文件之間的關係。當從根目錄讀取文件時,讀取系統上的文件路徑是從左到右讀取的,可是當從根目錄讀取DN時,是從右到左讀DN的。如:
uid = jordan,ou = nba,o = american
表示定義了在組織american中的小組爲nba的用戶jordan的用戶。其中一個DN名的最左邊部分叫相對區分名稱RDN(relative distinguished name),它由一個條目內的屬性/值組成,如前面的uid = jordan是RDN,後面的無關緊要。
LDAP一般使用簡寫形式的助記符表示其名稱,經常使用的LDAP屬性及其定義如表6-1所示。
LDAP屬性及其定義
LDAP屬性 |
定義 |
o |
Organization:組織 |
ou |
Organization unit:組織單元 |
續表
LDAP屬性 |
定義 |
uid |
Userid:用戶id |
cn |
Common name:常見名稱 |
sn |
姓 |
givenname |
首名 |
dn |
Distinguished Name:區分名稱 |
|
E-mail Address:電子郵件地址 |
其中一個屬性能夠有一個或多個值,如一個用戶能夠有多個mail。
2.LDAP的功能
到目前爲止,咱們已經介紹了LDAP行程註冊部分,其實LDAP中還包括不少其餘的用途,總的來講LDAP的功能包括遠程服務的註冊、訪問控制、黃頁服務器和配置 數據。
(1)遠程服務器註冊
這是本章中使用LDAP時所涉及的內容,前面已經談到過該項功能。LDAP容許遠程服務器註冊其可用性,而後容許客戶機得到該註冊信息,而且可以使用該服務器。在某些狀況下(如RMI),這可能意味着將可序列化的對象保存在LDAP中,而且在此後能夠檢索這些已保存的對象。這相似於rmiregistry的使用方法,但它能搜索LDAP,而rmiregistry卻不能,而且當中止並從新啓動rmiregistry後,原來註冊的對象無效,必須從新註冊全部對象。
(2)訪問控制
許多企業應用程序都會對訪問它們服務的用戶進行控制。這可能像Web應用登陸頁面那樣簡單,也可能像使用數字簽名那樣複雜。不管是使用哪一種方法,那些待檢查的信息總須要保存到某個地方,有一種選擇是將這些信息保存到LDAP內。例如,能夠將用戶保存在LDAP中。
(3)黃頁服務器
黃頁服務器的做用相似於電話目錄,所以稱爲黃頁。它提供信息搜索功能,可使LDAP根據條目的屬性內容進行信息搜索。如對於用戶姓名、計算機和打印機等,都可以使用LDAP存儲公司內全部員工的這些信息,而後根據名字爲某個特定名字的用戶以及檢索他們的用戶ID搜索。
(4)配置數據
LDAP能夠充當配置信息的資源中心,這些配置信息在應用程序運行時使用。這相似於在Java應用程序中使用屬性文件,可是這並不只僅是每個應用程序的屬性文件,而是做爲一個可用來訪問而且還必須進行維護的單一的信息庫中心。如一些特定應用程序使用的共享數據庫名稱能夠保存到LDAP中。所以,若是數據庫名稱發生變動時,對於全部須要遷移到新數據庫的應用程序來說僅僅須要維護一個地方。
3.使用LDAP
爲了使用LDAP,須要完成如下4個步驟。
(1)鏈接到LDAP服務器
要使用LDAP,必須首先獲取一個到LDAP的鏈接。爲了完成LDAP的鏈接,須要知道運行LDAP的主機和要鏈接的端口,這有點相似於將電話線插到牆壁的電話孔後纔可以與別人打電話。
(2)綁定到LDAP服務器
對於LDAP,一般至少有兩種方法來綁定(登陸)到LDAP服務器,匿名(LDAP3以上版本)或者做爲特定用戶。綁定有些相似於使用電話公司設置的電話線撥打朋友的電話。匿名登陸僅僅可以訪問到一些公共數據。若是應用程序做爲特定用戶登陸時,就能夠訪問公共數據和特定爲該用戶設置的可訪問的全部數據。而爲某個用戶設置可訪問的數據是由LDAP服務器的訪問控制列表(access control list,ACL)決定。ACL控制哪一個用戶可以讀、寫或者修改該ACL所關聯的任何數據。一個條目內的不一樣屬性能夠與多個不一樣的ACL相關聯。所以,不一樣的用戶就可以看到不一樣的數據項,除此以外,某些特定的屬性能夠與多個ACL相關聯,如一個ACL能夠向一個用戶組提供讀的權限,可是另外一個ACL能夠向另外一個用戶組提供寫的權限。
(3)在LDAP服務器上執行所需的任何操做
這些操做主要包括搜索服務器、增長新條目、修改條目、刪除條目等。
(4)釋放LDAP服務器的鏈接
當應用程序鏈接到LDAP並完成其相關工做後,該應用程序應該關閉鏈接以釋放系統資源。
不使用服務提供者就不能用JNDI。一個服務提供者就是一組Java類的集合,它支持開發者同目錄服務進行通訊,其方式相似於JDBC驅動程序與數據庫之間的通訊方式。可以用於JNDI的服務提供者必須實現Context接口或Context的擴展接口Directory- Context。
在使用JNDI時,讀者只須要了解JNDI,而服務提供者才關注實際的網絡協議、編碼/解碼值等細節。
當下載SDK軟件開發包時,同時就下載了Sun公司的一些現有的服務提供者。這些服務提供者包括LDAP、NIS、COS(CORBA對象服務)、RMI註冊及文件系統的提供者。如:hashtableObj.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.ldapCtx- Fatory")就是表示使用Sun LDAP服務提供者。固然若是要使用IBM服務提供者時就能夠用com.ibm.jndi.LDAPCtxFatory來代替com.sun.jndi.ldap.ldapCtxFatory。
JNDI中包括5個包。
· javax.naming:主要用於命名操做,它包含了命名服務的類和接口,該包定義了Context接口和InitialContext類;
· javax.naming.directory:主要用於目錄操做,它定義了DirContext接口和InitialDir- Context類;
· javax.naming.event:在命名目錄服務器中請求事件通知;
· javax.naming.ldap:提供LDAP支持;
· javax.naming.spi:容許動態插入不一樣實現,爲不一樣命名目錄服務供應商的開發人員提供開發和實現的途徑,以便應用程序經過JNDI能夠訪問相關服務。
經常使用的JNDI操做以下:
· void bind(String sName,Object object),綁定:把名稱同對象關聯的過程。
· void rebind(String sName,Object object),從新綁定:用來把對象同一個已經存在的名稱從新綁定。通常使用rebind()而不使用bind(),由於當有重名的時候rebind()不會出現異常,而bind()會報異常。
· void unbind(String sName),釋放:用來把對象從目錄中釋放出來。
· void lookup(String sName,Object object),查找:返回目錄總的一個對象。
· void rename(String sOldName,String sNewName),重命名:用來修改對象名稱綁定的名稱。
· NamingEnumeration listBindings(String sName),清單:返回綁定在特定上下文中指定屬性名對象的清單列表,它返回名字、類和對象自己,它用於那些須要對對象進行實際操做的應用。具體使用以下:
//獲得初始目錄環境的一個引用
Context cntxt = new InitialContext();
//返回綁定在特定上下文中指定屬性名對象的清單列表
NamingEnumeration namEnumList = ctxt.listBinding("cntxtName");
//循環列出全部名字、類和對象
while ( namEnumList.hasMore() ) {
Binding bnd = (Binding) namEnumList.next();
String sObjName = bnd.getName();
String sClassName = bnd.getClassName();
//獲得對象
SomeObject objLocal = (SomeObject) bnd.getObject();
}
· NamingEnumeration list(String sName)與listBindings(String sName)類似,只是它只返回一系列名字/類映射,它主要是用於上下文瀏覽應用。
使用JNDI來訪問命名服務或者目錄服務,操做步驟以下:
(1)創建一個散列表(hashtable),它包含定義所但願使用的JNDI服務的屬性,所但願鏈接的LDAP服務器IP地址以及工做的端口。
(2)將與認證成爲用戶登陸有關的任何信息添加到散列表中。
(3)建立初始context對象。若是訪問命名服務,則使用InitialContext類,若是訪問目錄服務,則要使用InitialDirContext類。
(4)使用剛纔獲得的context對象執行所需的操做(如添加新的條目或者搜索條目)。
(5)完成操做後關閉context對象。
JNDI最大的功能是能使用LDAP來存儲須要在不一樣應用之間共享或者留作備用的對象。JNDI容許將下面幾種與Java相關的對象類型存儲到LDAP服務器內。
(1)串行化的Java對象。這是存儲和取回已經串行化的Java對象的能力。也就是 說要存儲的Java對象必需要實現Referenceable或Serializable接口類,不然該對象不能存儲。
(2)標準的LDAP目錄條目。它提供了操做標準目錄數據的能力。標準目錄數據的數據量比較小,能夠在不一樣的語言之間共享它們。保持目錄數據與編程語言的無關性對於要使用幾種不一樣語言進行開發的大企業裏是很是重要的。
(3)指向RMI Java對象的指針。RMI是用於分佈式計算的,經過RMI,一個Java應用能夠像本地同樣調用一個遠程類的方法。咱們能夠把一個可用的RMI類的引用存儲在開發者的LDAP服務器中,而沒必要在每一個裝有RMI客戶應用的計算機上都保持可用方法的註冊。
JNDI的主要目標是在網絡上讀/寫Java對象。下面用具體實例來了解怎麼使用JNDI。首先經過一個例子來說解怎麼樣在LDAP中保存串行化的Java對象數據,再用一個例子來講明怎麼對保存的對象數據進行查詢、調用。
1.保存數據
在LDAP中保存數據就是在LDAP服務器中添加使用條目,也就是把條目綁定在服務器中。下面先創建一個基本類,再在另外一個類中利用JNDI把這個基本類綁定在服務器中。
4 例6-1 在LDAP中保存數據。
(1)待綁定的基本類
package jndi;
import java.io.serializable;
public class persons implements Serializable {
String Name = "";
String Age ="" ;
public persons () {
}
//構造函數,用於給變量賦值
public persons (String namePara,String age) {
Name = namePara;
Age = age;
}
//用於返回變量Name的值
public String getName() {
return Name;
}
//用於返回變量Age的值
public String getAge () {
return Age;
}
}
JNDI定義了一個Serializable接口類來爲應用信息的表達提供一種統一的方式。Serializable接口類包含了諸如地址、類型信息等用於訪問具體對象的信息。爲了能將對象的引用綁定到目錄樹中,該對象的類必須實現Referenceable接口,其中包含了方法 getReference()。開發者能夠在該對象上調用getReference()方法來得到Reference以用於綁定。Serializable接口與Referenceable接口有頗多類似之處,不一樣在於Referenceable可引用的對象只包含一些用於建立實際對象的信息,而Serializable會包含更多的甚至不適合存儲在目錄結構中的信息。
(2)綁定保存對象程序
package jndi;
import java.util.Hashtable;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.*;
public class ldapDataBind {
public static void main(String[]args){
//建立Hashtable以存儲JNDI將用於鏈接目錄服務的環境變量
Hashtable hs = new Hashtable();
//設置鏈接LDAP的實現工廠
hs.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
// 指定LDAP服務器的主機名和端口號
hs.put(Context.PROVIDER_URL, "ldap://localhost:389 ");
//給環境提供認證方法,有SIMPLE、SSL/TLS和SASL
hs.put(Context.SECURITY_AUTHENTICATION, "simple");
//指定進入的目錄識別名DN
hs.put(Context.SECURITY_PRINCIPAL, "cn=Directory Manager");
//進入的目錄密碼
hs.put(Context.SECURITY_CREDENTIALS, "password");
try {
// 獲得初始目錄環境的一個引用
DirContext ctx = new InitialDirContext(hs);
// 新建一個對象
persons perObj = new persons("jordan","40");
//綁定對象
ctx.rebind ("uid = Jordan,ou = Bull,o = NBA ",perObj);
System.out.println("bind object object success " );
/*實例化一個屬性集合*/
Attributes attrs = new BasicAttributes(true);
/*創建一個屬性,其屬性名爲"mail"*/
Attribute personMail = new BasicAttribute("mail");
//設置屬性"mail"的值爲"xie@163.com"、"liu@sina.com.cn"、
"xyh@powerise.com.cn"
personMail.add("xie@163.com");
personMail.add("liu@sina.com.cn");
personMail.add("xyh@powerise.com.cn");
attrs.put(personMail);
/*創建一個屬性,其屬性名爲"uid",值爲001*/
attrs.put("uid","001");
/*創建一個屬性,其屬性名爲"cn",值爲jordan1*/
attrs.put("cn","jordan1");
/*創建一個屬性,其屬性名爲"sn",值爲NBA */
attrs.put("sn","NBA");
/*創建一個屬性,其屬性名爲"ou",值爲bull */
attrs.put("ou","bull");
System.out.println("bind object object success " );
/* 在識別名爲DN的目錄中增長一個條目*/
ctx.createSubcontext("uid = Jordan, ou = Wizzard,o=NBA",attrs);
//關閉初始目錄環境
ctx.close();
} catch (NamingException ex) {
System.err.println("bind object fail: " + ex.toString());
}
}
}
2.使用JNDI查找數據
前面已經介紹了怎麼樣將對象數據綁定到服務器,如今開始介紹如何取得調用綁定在服務器上的對象數據。
5 例6-2 使用JNDI查找數據。
要調用對象數據,首先就必須用JNDI查找綁定的對象和數據,查找出來後,再調用該對象。程序以下所示。
package jndi;
import java.nutil.Hashtable;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.NamingEnumeration;
import javax.naming.directory.*;
public class findUseBindObj {
public static void main(String[]args){
//建立Hashtable以存儲JNDI將用於鏈接目錄服務的環境變量
Hashtable hs = new Hashtable();
//設置鏈接Ldap的實現工廠
hs.put(Context.INITIAL_CONTEXT_FACTORY,
"com.sun.jndi.ldap.LdapCtxFactory");
// 指定LDAP服務器IP地址爲本機及端口號爲389
hs.put(Context.PROVIDER_URL, "ldap://localhost:389");
try {
// 獲得初始目錄環境的一個引用
DirContext ctx = new InitialDirContext(hs);
//利用lookup查找返回指定DN的條目對象
persons pers =(persons)ctx.lookup("uid=Jordan,ou=Bull,o=NBA");
// 利用遠程對象調用遠程方法,返回Age變量的值
String age = pers.getAge();
// 利用遠程對象調用遠程方法,返回Name變量的值
String name = pers.getName();
//輸出Name的值
System.out.println("name is :" + name );
/*根據結點的DN來查找它的全部屬性, 而後再從屬性中獲得全部的值,注意一個屬性可
以有多個值*/
Attributes attrs=ctx.getAttributes("uid=Jordan,ou=Wizzard,o=NBA");
//循環獲取並輸出這個屬性的全部屬性值
for(NamingEnumeration ae = attrs.getAll();ae.hasMore();){
//獲取一個屬性
Attribute attr = (Attribute)ae.next();
System.out.println("Attribute : " + attr.getID());
//循環取得輸出這個屬性的全部屬性值
for(NamingEnumeration ve = attr.getAll();ve.hasMore();){
System.out.println(" Value : " + ve.next());
}
}
//成功打印提示信息
System.out.println("find object success " );
//調用該對象的函數
pers.toString();
//關閉初始目錄環境
ctx.close();
} catch (NamingException ex) {
System.err.println(ex.toString());
}
}
}
對於做爲引用綁定在目錄樹中的對象,JNDI SPI 指定針對引用建立實際的對象。所以,在程序中只須要認爲用lookup()方法返回的對象就是實際對象,而不用在調用什麼方法來將引用轉換爲實際對象了,由於全部的工做都由JNDI內部完成了。
前面已經介紹瞭如何在LDAP服務器裏存儲一個對象:主要是利用一個DN將對象綁定到LDAP服務器中,而後用lookup(DN)查找定位到綁定的對象,再對該對象進行操做。可是每每使用DN查找很是難,用戶很難記住DN,所以咱們可使用其餘屬性(好比CN=Cherry)來檢索包含那個屬性的條目。下面來介紹JNDI中相關屬性檢索的具體使用。
1.修改條目
不少時候可能要對LDAP服務器上的條目進行修改,如修改用戶密碼,更新應用的配置等。但修改必須由一個已認證過的用戶來執行,並且一般只能修改本身的密碼而不能修改其餘信息,管理助手可以修改電話號碼和郵件地址,而修改用戶標識這種工做由數據庫管理員完成。
6 例6-3 用JNDI修改LDAP條目。
package jndi;
import java.nutil.Hashtable;
import javax.naming.Context;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.ModificationItem;
public class jndiPropertyModify {
public static void main(String[] args){
Hashtable hs = new Hashtable();
//設置鏈接LDAP的實現工廠爲com.sun.jndi.ldap.LdapCtxFactory
hs.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.
LdapCtxFactory");
//指定提供服務的服務器IP地址和端口號
hs.put(Context.PROVIDER_URL,"ldap://localhost:389");
//使用簡單認證來認證用戶
hs.put(Context.SECURITY_AUTHENTICATION,"simple");
hs.put(Context.SECURITY_PRINCIPAL,"uid=Jordan,ou=Bull,o=NBA");
hs.put(Context.SECURITY_CREDENTIALS,"good");
try {
/*指定了JNDI服務提供者中工廠類(factory class)的名稱。Factory負
責爲其服務建立適當的InitialContext對象。在上面的代碼片段中,爲文件
系統服務提供者指定了工廠類*/
DirContext ctx = new InitialDirContext(hs);
System.out.println("成功建立初始化context對象!");
//新建生成一個修改條目類對象,用於存放條目屬性
ModificationItem[] mdi = new ModificationItem[2];
// 把屬性mail的值置爲jordan@163.com
Attribute att0 = new BasicAttribute("mail",
"jordan@163.com");
// 把屬性call的值置爲12745827
Attribute att1 = new BasicAttribute("call","12745827");
//修改指定屬性mail
mdi[0]=new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
att0);
//增長新屬性call到條目
mdi[1]=new ModificationItem(DirContext.ADD_ATTRIBUTE,att1);
// 修改指定DN條目的屬性
ctx.modifyAttributes("uid=Jordan,ou=Bull,o=NBA",mdi);
}catch(Exception ex ){
ex.printStackTrace();
System.exit(1);
}
}
}
上面程序的做用是修改前面例子中增長的DN爲uid = Jordan,ou = Bull,o = NBA條目的屬性。
在程序中用DirContext.REPLACE_ATTRIBUTE來修改條目的mail屬性,在這裏若是原來的mail屬性有多個值時,都會被刪掉,取而代之的是新賦的值。用DirContext. REPLACE_ATTRIBUTE時,若是原來的屬性(mail)不存在時,就增長一個屬性,有則修改。
用DirContext.ADD_ATTRIBUTE來將一個新屬性增長到條目。真正起到修改做用的是ctx.modifyAttributes("uid = Jordan,ou = Bull,o = NBA",mdi)這條語句。
2.刪除條目
有時,當開發者不須要某個條目時,就能夠把它從LDAP服務器上刪除。這隻要經過調用參數爲指定DN條目的DirContext接口的destorySubContext()方法來完成。
7 例6-4 用JNDI刪除LDAP條目。
package jndi;
import java.nutil.Hashtable;
import javax.naming.Context;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.ModificationItem;
public class jndiPropertyModify {
public static void main(String[] args){
Hashtable hs = new Hashtable();
//設置鏈接LDAP的實現工廠爲com.sun.jndi.ldap.LdapCtxFactory
hs.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.
LdapCtxFactory");
//指定提供服務的服務器IP地址和端口號
hs.put(Context.PROVIDER_URL,"ldap://localhost:389");
//使用簡單認證來認證用戶
hs.put(Context.SECURITY_AUTHENTICATION,"simple");
// 指定DN
hs.put(Context.SECURITY_PRINCIPAL,"uid=Jordan,ou=Bull,o=NBA");
// 指定認證密碼
hs.put(Context.SECURITY_CREDENTIALS,"good");
try {
/*指定了JNDI服務提供者中工廠類(factory class)的名稱。Factory負
責爲其服務建立適當的InitialContext對象。在上面的代碼片段中,爲文件
系統服務提供者指定了工廠類*/
DirContext ctx = new InitialDirContext(hs);
//刪除指定DN條目
ctx.destroySubcontext("uid=Jordan,ou=Bull,o=NBA");
}catch(Exception ex ){
ex.printStackTrace();
System.exit(1);
}
}
}