posts - 23,comments - 12,trackbacks - 0
          ?

          ??? LDAP的英文全稱是Lightweight Directory Access Protocol,即輕量級(jí)目錄訪問(wèn)協(xié)議.我們
          知道,人們對(duì)計(jì)算機(jī)網(wǎng)絡(luò)的使用和管理涉及了各種龐雜的資源,信息.為了提高性能,便于使
          用,有效管理分布式應(yīng)用的服務(wù),資源,用戶及別的對(duì)象信息,這些信息需要清晰,一致地組
          織起來(lái).基于這樣的需求,描述各種用戶,應(yīng)用,文件,打印機(jī)和其它可從網(wǎng)絡(luò)訪問(wèn)的資源的
          信息被集中到一個(gè)特殊的數(shù)據(jù)庫(kù)中,這種數(shù)據(jù)庫(kù)被稱為目錄.目錄存放對(duì)象的公開(kāi)或非公開(kāi)的
          信息,這些信息以某種順序組織,描述了每個(gè)對(duì)象的細(xì)節(jié).電話簿,圖書館藏書卡片目錄就是
          常見(jiàn)的目錄.
          ???? LDAP是基于X.500標(biāo)準(zhǔn)的,訪問(wèn) X.500 目錄需要某種協(xié)議,例如:目錄訪問(wèn)協(xié)議 (DAP).
          然而,DAP 需要大量的系統(tǒng)資源和支持機(jī)制來(lái)處理復(fù)雜的協(xié)議.LDAP 僅通過(guò)使用原始 X.500
          目錄存取協(xié)議 (DAP) 的功能子集而減少了所需的系統(tǒng)資源消耗,而且可以根據(jù)需要定制.此
          外,與X.500不同,LDAP支持TCP/IP,這對(duì)訪問(wèn)Internet是必須的.
          ??? 為了能對(duì)LDAP協(xié)議進(jìn)行更好的理解,我們需要對(duì)以下概念有初步的認(rèn)識(shí):
          目錄:Directory,存放對(duì)象的信息,這些信息以某種順序組織,詳細(xì)描述每個(gè)對(duì)象.
          目錄信息樹(shù):DIT,Directory Information Tree,目錄條目的集合構(gòu)成了目錄信息樹(shù).
          條目:Entry,目錄信息樹(shù)中的一個(gè)結(jié)點(diǎn),是一個(gè)對(duì)象信息的集合,是目錄信息中最基本的
          單位,包含該對(duì)象的一系列屬性.
          屬性:Attribute,屬性描述對(duì)象的特征.一個(gè)屬性由屬性類型(type)和一個(gè)或多個(gè)屬性值
          (values)構(gòu)成.
          相對(duì)標(biāo)識(shí)名:RDN,Relative Distinguished Name,條目的名字.
          唯一標(biāo)識(shí)名:DN,Distinguished Name,在一個(gè)目錄信息樹(shù)中唯一標(biāo)識(shí)一個(gè)條目的名字.
          ??? LDAP(輕量級(jí)目錄訪問(wèn)協(xié)議,Lightweight Directory Access Protocol)是實(shí)現(xiàn)提供被稱為目錄服務(wù)的信息服務(wù)。
          目錄服務(wù)是一種特殊的數(shù)據(jù)庫(kù)系統(tǒng),其專門針對(duì)讀取,瀏覽和搜索操作進(jìn)行了特定的優(yōu)化。目錄一般用來(lái)包含描
          述性的,基于屬性的信息并支持精細(xì)復(fù)雜的過(guò)濾能力。目錄一般不支持通用數(shù)據(jù)庫(kù)針對(duì)大量更新操作操作需要的
          復(fù)雜的事務(wù)管理或回卷策略。而目錄服務(wù)的更新則一般都非常簡(jiǎn)單。這種目錄可以存儲(chǔ)包括個(gè)人信息、web鏈結(jié)、
          jpeg圖像等各種信息。為了訪問(wèn)存儲(chǔ)在目錄中的信息,就需要使用運(yùn)行在TCP/IP之上的訪問(wèn)協(xié)議—LDAP。

          ??? LDAP目錄中的信息是是按照樹(shù)型結(jié)構(gòu)組織,具體信息存儲(chǔ)在條目(entry)的數(shù)據(jù)結(jié)構(gòu)中。條目相當(dāng)于關(guān)系數(shù)據(jù)庫(kù)中
          表的記錄;條目是具有區(qū)別名DN(Distinguished Name)的屬性(Attribute),DN是用來(lái)引用條目的,DN相當(dāng)于
          關(guān)系數(shù)據(jù)庫(kù)表中的關(guān)鍵字(Primary Key)。屬性由類型(Type)和一個(gè)或多個(gè)值(Values)組成,相當(dāng)于關(guān)系數(shù)
          據(jù)庫(kù)中的字段(Field)由字段名和數(shù)據(jù)類型組成,只是為了方便檢索的需要,LDAP中的Type可以有多個(gè)Value,
          而不是關(guān)系數(shù)據(jù)庫(kù)中為降低數(shù)據(jù)的冗余性要求實(shí)現(xiàn)的各個(gè)域必須是不相關(guān)的。LDAP中條目的組織一般按照地理位置
          和組織關(guān)系進(jìn)行組織,非常的直觀。LDAP把數(shù)據(jù)存放在文件中,為提高效率可以使用基于索引的文件數(shù)據(jù)庫(kù),而不
          是關(guān)系數(shù)據(jù)庫(kù)。類型的一個(gè)例子就是mail,其值將是一個(gè)電子郵件地址。

          WebLogic的內(nèi)置的LDAP Server支持IETF LDAP為L(zhǎng)DAPv3制定的控制訪問(wèn)模型。下面這個(gè)片斷將講述在內(nèi)置的LDAP
          Server中怎樣實(shí)現(xiàn)控制訪問(wèn)。可以通過(guò)編輯訪問(wèn)控制文件來(lái)將這些規(guī)則直接應(yīng)用到目錄的入口。
          WebLogic中的訪問(wèn)控制文件是acls.prop。在Server的lib中可以找到這個(gè)文件。
          這個(gè)文件的所有訪問(wèn)控制規(guī)則都被注釋掉了,如果想更改這些規(guī)則,你要手工更改這個(gè)文件。
          注意:WebLogic Server內(nèi)置的LDAP Server在默認(rèn)的情況下只允許Admin帳號(hào)訪問(wèn),WebLogic Server的security providers
          只使用Admin帳號(hào)訪問(wèn)內(nèi)置的LDAP Server。如果你不想使用外部的LDAP Brower訪問(wèn)WebLogic Server的內(nèi)置的LDAP Server,
          或者你只想使用Admin帳號(hào)訪問(wèn)內(nèi)置的LDAP Server,你不需要編輯acls.prop文件,
          訪問(wèn)控制文件(The Access Control File)

          訪問(wèn)控制文件(acls.prop)包含內(nèi)置的LDAP Server的整個(gè)目錄的完整的訪問(wèn)控制列表(ACL)。
          這個(gè)文件中的每一行都包含一個(gè)訪問(wèn)控制規(guī)則。一個(gè)訪問(wèn)控制規(guī)則由下面接個(gè)部分組成:
          ??? 訪問(wèn)控制位置(Access Control Location)
          ?????? 每個(gè)訪問(wèn)控制規(guī)則都應(yīng)用于LDAP目錄中的一個(gè)給定的位置。這個(gè)位置通常是一個(gè)區(qū)別命名(DN),但有一個(gè)例外,這就是[root],如果訪問(wèn)控制規(guī)則應(yīng)用到整個(gè)目錄,則只需要指定位置為[root]就可以了!
          ?????? 如果被訪問(wèn)或更改的入口的位置與訪問(wèn)控制規(guī)則指定的位置不相等,或在訪問(wèn)控制規(guī)則指定的位置的下級(jí),則這個(gè)訪問(wèn)控制規(guī)則將不會(huì)被執(zhí)行。

          ?? 訪問(wèn)控制范圍(Access Control Scope)
          ?????? 訪問(wèn)控制范圍有2種:
          ?????? Entry-一個(gè)Entry范圍的訪問(wèn)控制列表只在下面的情況下被執(zhí)行:
          ?????? LDAP目錄的入口的DN與訪問(wèn)控制規(guī)則指定的位置相同。這樣的規(guī)則對(duì)于包含了比并行和副入口更敏感信息的單獨(dú)入口非常有用。
          ?????? Subtree-意味著訪問(wèn)控制規(guī)則指定的位置及子樹(shù)都可以適用這條規(guī)則。
          ??????? 如果Entry與Subtree在訪問(wèn)控制規(guī)則中有沖突,則Entry要優(yōu)先于Subtree。

          ?? 訪問(wèn)權(quán)限(Access Rights)
          ??????? 訪問(wèn)權(quán)限應(yīng)用于整個(gè)對(duì)象或?qū)ο蟮膶傩裕?個(gè)值:grant(準(zhǔn)許)或deny(拒絕)。訪問(wèn)權(quán)限指定了LDAP操作的類型。
          ??
          ?? 許可(grant或deny)

          ?? 應(yīng)用規(guī)則的屬性(attribute)

          ?? 允許或拒絕訪問(wèn)的主題(subject)
          ?? 在weblogic可以編寫程序來(lái)訪問(wèn)LDAP.上手時(shí)可以選擇JXplorer工具。
          ?? 1.LDAP Server及LDAP Browser:
          ????? 對(duì)于WLS LDAP為理解起來(lái)簡(jiǎn)單,去掉限制的方法是修改bea\weblogic81\server\lib\acls.prop文件后。修改方法:
          在該文件最后添加以下幾行。
          [root]|entry#grant:s,r,o,w,c,m#[all]#public
          [root]|subtree#grant:s,r,o,w,c,m#[all]#public:
          [root]|subtree#grant:a,d,e,i,n,b,t#[entry]#public:
          cn=schema|entry#grant:s,r,o,w,c,m#[all]#public:
          cn=schema|entry#grant:a,d,e,i,n,b,t#[entry]#public:
          注意,該文件中這些行之間,以及其他行之間不能有空行,否則啟動(dòng)WLS會(huì)報(bào)錯(cuò)的。修改好之后就可以啟動(dòng)WLS了,
          啟動(dòng)后進(jìn)入Console里修改Ldap Server的密碼。密碼修改完后需要再重新啟動(dòng)一次WLS。
          LDAP剛上手的時(shí)候沒(méi)有方便的工具會(huì)很費(fèi)勁。我看了CSDN上“兔八哥”的文章,用JXplorer,感覺(jué)很不錯(cuò)。
          想看這篇文章,到CSDN上搜一下“兔八哥”,系列中No.12就是關(guān)于JXplorer的配置和使用。我的連接參數(shù)如下:
          Host:localhost//根據(jù)實(shí)際修改
          Port:7001
          Protocol:LDAP v3
          Base DN:dc=ldapdomain//根據(jù)實(shí)際修改
          Level:User+Password
          User DN:cn=Admin
          Password:weblogic//根據(jù)實(shí)際修改
          .編程操作LDAP Server。
          ?下面四個(gè)JAVA方法,分別用于初始化,查詢,添加,刪除,修改,關(guān)閉連接。
          ?記得每次都需要先大概連接,操作,然后關(guān)閉連接。和使用數(shù)據(jù)庫(kù)差不多。
          ?
          ?????? 首先是需要用到的頭文件:
          import java.util.Hashtable;
          import java.util.Enumeration;
          import javax.naming.Context;
          import javax.naming.NamingException;
          import javax.naming.directory.DirContext;
          import javax.naming.directory.InitialDirContext;
          import javax.naming.directory.SearchControls ;
          import javax.naming.NamingEnumeration;
          import javax.naming.directory.SearchResult;
          import javax.naming.directory.Attributes ;
          import javax.naming.directory.Attribute;
          import javax.naming.directory.BasicAttributes;
          import javax.naming.directory.BasicAttribute;
          import javax.naming.directory.ModificationItem;
          import java.lang.reflect.Method;
          import java.io.BufferedReader;
          import java.io.InputStreamReader;


          然后是一個(gè)類域,用于保存上下文:
          ?
          DirContext ctx = null;
          ?
          然后是初始化:
          ?
          ??? public void init(){
          ??????? String account="Admin";//操作LDAP的帳戶。默認(rèn)就是Admin。
          ??????? String password="weblogic";//帳戶Admin的密碼。
          ??????? String root="dc=ldapdomain"; //所操作的WLS域。也就是LDAP的根節(jié)點(diǎn)的DC
          ??????? Hashtable env = new Hashtable();
          ??????? env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");//必須這樣寫,無(wú)論用什么LDAP服務(wù)器。
          ??????? env.put(Context.PROVIDER_URL, "ldap://localhost:7001/" + root);//LDAP服務(wù)器的地址:端口。對(duì)WLS端口就是7001
          ??????? env.put(Context.SECURITY_AUTHENTICATION, "none");//授權(quán)界別,可以有三種授權(quán)級(jí)別,但是如果設(shè)為另外兩種都無(wú)法登錄,我也不知道為啥,但是只能設(shè)成這個(gè)值"none"。
          ??????? env.put(Context.SECURITY_PRINCIPAL, "cn=" + account + "," + root);//載入登陸帳戶和登錄密碼
          ??????? env.put(Context.SECURITY_CREDENTIALS, password);
          ??????? try{
          ??????????? ctx = new InitialDirContext(env);//初始化上下文
          ??????????? System.out.println("認(rèn)證成功");//這里可以改成異常拋出。
          ??????? }catch(javax.naming.AuthenticationException e){
          ??????????? System.out.println("認(rèn)證失敗");
          ??????? }catch(Exception e){
          ??????????? System.out.println("認(rèn)證出錯(cuò):"+e);
          ??????? }
          ?}


          查詢操作:
          ?
          ?public void search(){//我只能按照某些屬性查找節(jié)點(diǎn),偶還不會(huì)怎么查找一個(gè)目錄或按照更復(fù)雜的正則式查找特定節(jié)點(diǎn)/目錄
          ? try{
          ?? SearchControls constraints = new SearchControls();
          ?? constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);
          ?? System.out.print("what would you want to search:");
          ?? BufferedReader bd=new BufferedReader(new InputStreamReader(System.in));
          ?? String s=bd.readLine();
          ?? NamingEnumeration en = ctx.search("", "uid="+s, constraints); //要查詢的UID。如果是*則可以查到所有UID的節(jié)點(diǎn)
          ?? if(en == null){
          ??? System.out.println("Have no NamingEnumeration.");
          ?? }
          ?? if(!en.hasMoreElements()){
          ??? System.out.println("Have no element.");
          ?? }
          ?? while (en != null && en.hasMoreElements()){//可以查出多個(gè)元素
          ?????? Object obj = en.nextElement();
          ?????? if(obj instanceof SearchResult){
          ?????????? SearchResult si = (SearchResult) obj;
          ?????????? System.out.println("\tname: " + si.getName());
          ?????????? Attributes attrs = si.getAttributes();
          ?????????? if (attrs == null){
          ?????????????? System.out.println("\tNo attributes");
          ?????????? }else{
          ?????????????? for (NamingEnumeration ae = attrs.getAll(); ae.hasMoreElements();){//獲得該節(jié)點(diǎn)的所有屬性
          ?????? Attribute attr = (Attribute) ae.next();//下一屬性
          ?????? String attrId = attr.getID();//獲得該屬性的屬性名
          ?????? for (Enumeration vals = attr.getAll();vals.hasMoreElements();){//獲得一個(gè)屬性中的所有屬性值
          ?????????? System.out.print("\t\t"+attrId + ": ");
          ?????????? Object o = vals.nextElement();//下一屬性值
          ?????????? if(o instanceof byte[])
          ?????????????? System.out.println(new String((byte[])o));
          ?????????? else
          ?????????????? System.out.println(o);
          ?????? }
          ?????????????? }
          ?????????? }
          ?????? }
          ?????? else{
          ?????????? System.out.println(obj);
          ?????? }
          ?????? System.out.println();
          ?? }
          ? }catch(Exception e){
          ?? System.out.println("Exception in search():"+e);
          ? }
          ??? }
          ?
          添加操作:
          ?
          ??? public void add(){
          ???? try{
          ?? String newUserName = "stella";
          ?? BasicAttributes attrs = new BasicAttributes();
          ?? BasicAttribute objclassSet = new BasicAttribute("objectclass");
          ?? objclassSet.add("person");
          ?? objclassSet.add("top");
          ?? objclassSet.add("organizationalPerson");
          ?? objclassSet.add("inetOrgPerson");
          ?? objclassSet.add("wlsUser");
          ?? attrs.put(objclassSet);
          ?? attrs.put("sn", newUserName);
          ?? attrs.put("uid", newUserName);
          ?? attrs.put("cn", newUserName);
          ?? ctx.createSubcontext("uid=" + newUserName+",ou=people,ou=myrealm", attrs);? //添加一個(gè)節(jié)點(diǎn),我還不會(huì)添加目錄
          ? }catch(Exception e){
          ?? System.out.println("Exception in add():"+e);
          ? }
          ??? }


          修改操作:
          ?
          ??? public void edit(){
          ???? try{
          ?? String account = "stella";//修改以前舊的值
          ?? String sn = "stella sn";//修改以后新的值
          ?? ModificationItem modificationItem[] = new ModificationItem[1];
          ?? modificationItem[0] =
          ??? new ModificationItem(
          ???? DirContext.REPLACE_ATTRIBUTE,
          ???? new BasicAttribute("sn", sn));//所修改的屬性
          ?? ctx.modifyAttributes("uid=" + account, modificationItem);??? //執(zhí)行修改操作
          ? }catch(Exception e){
          ?? System.out.println("Exception in edit():"+e);
          ? }
          ??? }


          刪除節(jié)點(diǎn)操作:
          ?
          ??? public void delete(){
          ???? try{
          ?? String uid = "stella";
          ?? ctx.destroySubcontext("uid=" + uid);? //按照UID刪除某個(gè)節(jié)點(diǎn)。我還不會(huì)刪除一個(gè)目錄。
          ?? }catch(Exception e){
          ??? System.out.println("Exception in edit():"+e);
          ?? }
          ??? }


          關(guān)閉連接:
          ?
          ??? public void close(){
          ??????? if(ctx != null)
          ??????? {
          ??????????? try
          ??????????? {
          ??????????????? ctx.close();
          ??????????? }
          ??????????? catch (NamingException e)
          ??????????? {
          ??????????????? System.out.println("NamingException in close():"+e);
          ??????????? }
          ??????? }???
          ??? }
          我對(duì)LDAP的理解:它是用于對(duì)資源的管理和服務(wù)的訪問(wèn)協(xié)議,在Weblogic平臺(tái)上的JNDI(包含EJB和DataSource)都是提供它來(lái)提供的。
          正是JNDI的服務(wù)和RMI結(jié)合就形成J2EE平臺(tái)上分布式的應(yīng)用,因此說(shuō)到底層,還是LDAP協(xié)議的支持。

          posted on 2005-10-27 16:34 my java 閱讀(475) 評(píng)論(0)  編輯  收藏 所屬分類: JNDI
          主站蜘蛛池模板: 平谷区| 汝州市| 玉林市| 天峨县| 运城市| 洛阳市| 博爱县| 平顶山市| 中江县| 宁明县| 信阳市| 金乡县| 梅河口市| 白城市| 临夏市| 涪陵区| 衢州市| 新和县| 宁陵县| 天津市| 卢氏县| 隆尧县| 琼海市| 府谷县| 大同县| 宣城市| 井研县| 安国市| 图们市| 兴安县| 娱乐| 平陆县| 介休市| 勃利县| 浙江省| 万安县| 永泰县| 平陆县| 比如县| 德州市| 佛学|