隨筆-19  評論-128  文章-1  trackbacks-0

          LDAP快速入門

          1. LDAP簡介

            LDAP(輕量級目錄訪問協(xié)議,Lightweight Directory Access Protocol)是實現(xiàn)提供被稱為目錄服務(wù)的信息服務(wù)。目錄服務(wù)是一種特殊的數(shù)據(jù)庫系統(tǒng),其專門針對讀取,瀏覽和搜索操作進行了特定的優(yōu)化。目錄一般用來包含描述性的,基于屬性的信息并支持精細(xì)復(fù)雜的過濾能力。目錄一般不支持通用數(shù)據(jù)庫針對大量更新操作操作需要的復(fù)雜的事務(wù)管理或回卷策略。而目錄服務(wù)的更新則一般都非常簡單。這種目錄可以存儲包括個人信息、web鏈結(jié)、jpeg圖像等各種信息。為了訪問存儲在目錄中的信息,就需要使用運行在TCP/IP 之上的訪問協(xié)議—LDAP。

           

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

           

          LDAP的信息是以樹型結(jié)構(gòu)存儲的,在樹根一般定義國家(c=CN)或域名(dc=com),在其下則往往定義一個或多個組織 (organization)(o=Acme)或組織單元(organizational units) (ou=People)。一個組織單元可能包含諸如所有雇員、大樓內(nèi)的所有打印機等信息。此外,LDAP支持對條目能夠和必須支持哪些屬性進行控制,這是有一個特殊的稱為對象類別(objectClass)的屬性來實現(xiàn)的。該屬性的值決定了該條目必須遵循的一些規(guī)則,其規(guī)定了該條目能夠及至少應(yīng)該包含哪些屬性。例如:inetorgPerson對象類需要支持sn(surname)和cn(common name)屬性,但也可以包含可選的如郵件,電話號碼等屬性。

           

          2. LDAP簡稱對應(yīng)

          1. o– organization(組織-公司)
          2. ou – organization unit(組織單元-部門)
          3. c - countryName(國家)
          4. dc - domainComponent(域名)
          5. sn – suer name(真實名稱)
          6. cn - common name(常用名稱)

           

          3. 目錄設(shè)計

          設(shè)計目錄結(jié)構(gòu)是LDAP最重要的方面之一。下面我們將通過一個簡單的例子來說明如何設(shè)計合理的目錄結(jié)構(gòu)。該例子將通過Netscape地址薄來訪文。假設(shè)有一個位于美國US(c=US)而且跨越多個州的名為Acme(o=Acme)的公司。Acme希望為所有的雇員實現(xiàn)一個小型的地址薄服務(wù)器。

           

            我們從一個簡單的組織DN開始: 

              dn: o=Acme, c=US

           

            Acme所有的組織分類和屬性將存儲在該DN之下,這個DN在該存儲在該服務(wù)器的目錄是唯一的。Acme希望將其雇員的信息分為兩類:管理者(ou= Managers)和普通雇員(ou=Employees),這種分類產(chǎn)生的相對區(qū)別名(RDN,relative distinguished names。表示相對于頂點DN)就shi :

           

              dn: ou=Managers, o=Acme, c=US

              dn: ou=Employees, o=Acme, c=US

           

            在下面我們將會看到分層結(jié)構(gòu)的組成:頂點是US的Acme,下面是管理者組織單元和雇員組織單元。因此包括Managers和Employees的DN組成為:

              dn: cn=Jason H. Smith, ou=Managers, o=Acme, c=US

              dn: cn=Ray D. Jones, ou=Employees, o=Acme, c=US

              dn: cn=Eric S. Woods, ou=Employees, o=Acme, c=US

           

            為了引用Jason H. Smith的通用名(common name )條目,LDAP將采用cn=Jason H. Smith的RDN。然后將前面的父條目結(jié)合在一起就形成如下的樹型結(jié)構(gòu):

           

              cn=Jason H. Smith

                  + ou=Managers

                      + o=Acme

                          + c=US

                                         -> dn: cn=Jason H. Smith,ou=Managers,o=Acme,c=US

           

           

            現(xiàn)在已經(jīng)定義好了目錄結(jié)構(gòu),下一步就需要導(dǎo)入目錄信息數(shù)據(jù)。目錄信息數(shù)據(jù)將被存放在LDIF文件中,其是導(dǎo)入目錄信息數(shù)據(jù)的默認(rèn)存放文件。用戶可以方便的編寫Perl腳本來從例如/etc/passwd、NIS等系統(tǒng)文件中自動創(chuàng)建LDIF文件。

           

            下面的實例保存目錄信息數(shù)據(jù)為testdate.ldif文件,該文件的格式說明將可以在man ldif中得到。

            在添加任何組織單元以前,必須首先定義Acme DN: 

              dn: o=Acme, c=US

              objectClass: organization

           

            這里o屬性是必須的

              o: Acme

           

            下面是管理組單元的DN,在添加任何管理者信息以前,必須先定義該條目。

              dn: ou=Managers, o=Acme, c=US

              objectClass: organizationalUnit

          這里ou屬性是必須的。

           

          ou: Managers

            第一個管理者DN:

              dn: cn=Jason H. Smith, ou=Managers, o=Acme, c=US

              objectClass: inetOrgPerson

            cn和sn都是必須的屬性:

              cn: Jason H. Smith

              sn: Smith

            但是還可以定義一些可選的屬性:

              telephoneNumber: 111-222-9999

              mail: headhauncho@acme.com

              localityName: Houston

           

            可以定義另外一個組織單元:

              dn: ou=Employees, o=Acme, c=US

              objectClass: organizationalUnit

              ou: Employees

           

            并添加雇員信息如下:

              dn: cn=Ray D. Jones, ou=Employees, o=Acme, c=US

              objectClass: inetOrgPerson

              cn: Ray D. Jones

              sn: Jones

              telephoneNumber: 444-555-6767

              mail: jonesrd@acme.com

              localityName: Houston

              dn: cn=Eric S. Woods, ou=Employees, o=Acme, c=US

              objectClass: inetOrgPerson

              cn: Eric S. Woods

              sn: Woods

              telephoneNumber: 444-555-6768

              mail: woodses@acme.com

              localityName: Houston

           

           

          4. 配置OpenLDAP

          本文實踐了在 Windows 下安裝配 openldap,并添加一個條目,LdapBrowser 瀏覽,及 Java 程序連接 openldap 的全過程。

           

          1. 下載安裝 openldap for windows,當(dāng)前版本2.2.29下載地址:http://download.bergmans.us/openldap/openldap-2.2.29/openldap-2.2.29-db-4.3.29-openssl-0.9.8a-win32_Setup.exe

              相關(guān)鏈接:http://lucas.bergmans.us/hacks/openldap/

             安裝很簡單,一路 next 即可,假設(shè)我們安裝在 c:\openldap

           

          2. 配置 openldap,編輯 sldap.conf 文件

             1) 打開 c:\openldap\sldap.conf,找到

              include  C:/openldap/etc/schema/core.schema,在它后面添加

              include  C:/openldap/etc/schema/cosine.schema

              include  C:/openldap/etc/schema/inetorgperson.schema

           

              接下來的例子只需要用到以上三個 schema,當(dāng)然,如果你覺得需要的話,你可以把其他的 schema 全部添加進來

              include  C:/openldap/etc/schema/corba.schema

              include  C:/openldap/etc/schema/dyngroup.schema

              include  C:/openldap/etc/schema/java.schema

              include  C:/openldap/etc/schema/misc.schema

              include  C:/openldap/etc/schema/nis.schema

              include  C:/openldap/etc/schema/openldap.schema

           

             2) 還是在 sldap.conf 文件中,找到

              suffix  "dc=my-domain,dc=com"

              rootdn  "cn=Manager,dc=my-domain,dc=com"

              把這兩行改為

              suffix "o=teemlink,c=cn" 

              rootdn "cn=Manager,o=teemlink,dc=cn"

           

              suffix 就是看自己如何定義了,后面步驟的 ldif 文件就必須與它定義了。還要注意到這個配置文件中有一個 rootpw  secret,這個 secret 是 cn=Manager 的密碼,以后會用到,不過這里是明文密碼,你可以用命令: slappasswd -h {MD5} -s secret 算出加密的密碼 {MD5}Xr4ilOzQ4PCOq3aQ0qbuaQ== 取代配置中的 secret。

           

          3. 啟動 openldap

              CMD 進入到 c:\openldap 下,運行命令 sldapd -d 1

              用可以看到控制臺下打印一片信息,openldap 默認(rèn)是用的 Berkeley DB 數(shù)據(jù)庫存儲目錄數(shù)據(jù)的。

           

          4. 建立條目,編輯導(dǎo)入 ldif 文件

             1) 新建一個 ldif(LDAP Data Interchanged Format) 文件(純文本格式),例如 test.ldif,文件內(nèi)容如下:

             

          dn: o=teemlink

          objectclass: top

          objectclass: organization

          o: develop

           

             2) 執(zhí)行命令:ldapadd -l test.ldif

           

          5. 使用LDAP Browser進行訪問

                 5.1安裝LDAP Browser2.6軟件,進行如下操作:

             

            

           

          5.2顯示效果

           

           

          5. Java操作LDAP

           

          5.1 用JNDI進訪問

          package cn.myapps.test;

          import java.util.Hashtable;
          import javax.naming.Context;
          import javax.naming.NamingException;
          import javax.naming.directory.Attributes;
          import javax.naming.directory.DirContext;
          import javax.naming.directory.InitialDirContext;

          public class LdapTest {
          public void JNDILookup() {
          String root
          = "o=teemlink,c=cn";
          Hashtable env
          = new Hashtable();
          env.put(Context.INITIAL_CONTEXT_FACTORY,
          "com.sun.jndi.ldap.LdapCtxFactory");
          env.put(Context.PROVIDER_URL,
          "ldap://192.168.0.30/" + root);
          env.put(Context.SECURITY_AUTHENTICATION,
          "simple");
          env.put(Context.SECURITY_PRINCIPAL,
          "cn=Nicholas,ou=develop,o=teemlink,c=cn");
          env.put(Context.SECURITY_CREDENTIALS,
          "123456");
          DirContext ctx
          = null;

          try {
          ctx
          = new InitialDirContext(env);
          Attributes attrs
          = ctx.getAttributes("cn=Nicholas,ou=develop");
          System.out.println(
          "Last Name: " + attrs.get("sn").get());
          System.out.println(
          "認(rèn)證成功");
          }
          catch (javax.naming.AuthenticationException e) {
          e.printStackTrace();
          System.out.println(
          "認(rèn)證失敗");
          }
          catch (Exception e) {
          System.out.println(
          "認(rèn)證出錯:");
          e.printStackTrace();
          }
          if (ctx != null) {
          try {
          ctx.close();
          }
          catch (NamingException e) {
          // ignore
          }
          }
          }

          public static void main(String[] args) {
          LdapTest LDAPTest
          = new LdapTest();
          LDAPTest.JNDILookup();
          }
          }

           

          5.2 用JLDAP進訪問

          訪問地址:http://www.openldap.org/jldap/ 并下載相關(guān)lib

           

          import com.novell.ldap.*;

          import java.io.UnsupportedEncodingException;

          public class List

          {

          public static void main(String[] args)

          {
          int ldapPort = LDAPConnection.DEFAULT_PORT;
          int searchScope = LDAPConnection.SCOPE_ONE;
          int ldapVersion = LDAPConnection.LDAP_V3;
          boolean attributeOnly = false;
          String attrs[]
          = null;
          String ldapHost
          = "192.168.0.30";
          String loginDN
          = "cn=Manager,o=teemlink,c=cn";
          String password
          = "secret";
          String searchBase
          = "ou=develop,o=teemlink,c=cn";
          String searchFilter
          = "objectClass=*";

          LDAPConnection lc
          = new LDAPConnection();
          try {
          // connect to the server
          lc.connect(ldapHost, ldapPort);

          // bind to the server
          lc.bind(ldapVersion, loginDN, password.getBytes("UTF8"));

          LDAPSearchResults searchResults
          =

          lc.search(searchBase,
          // container to search
          searchScope, // search scope
          searchFilter, // search filter
          attrs, // "1.1" returns entry name only
          attributeOnly); // no attributes are returned

          // print out all the objects
          while (searchResults.hasMore()) {
          LDAPEntry nextEntry
          = null;
          try {
          nextEntry
          = searchResults.next();
          System.out.println(
          "\n" + nextEntry.getDN());
          System.out.println(nextEntry.getAttributeSet());
          }
          catch (LDAPException e) {
          System.out.println(
          "Error: " + e.toString());
          // Exception is thrown, go for next entry
          continue;
          }
          }

          // disconnect with the server
          lc.disconnect();

          }
          catch (LDAPException e) {
          System.out.println(
          "Error: " + e.toString());
          }
          catch (UnsupportedEncodingException e) {
          System.out.println(
          "Error: " + e.toString());
          }
          System.exit(
          0);
          }
          }

           

          5.3 用JDBC-LDAP進訪問

          訪問地址:http://www.openldap.org/jdbcldap/ 并下載相關(guān)lib

           

          package jdbcldap;

          import java.sql.Connection;
          import java.sql.DriverManager;
          import java.sql.ResultSet;
          import java.sql.Statement;

          public class JdbcLdap {

          /**
          *
          @param args
          *
          @throws Exception
          */
          public static void main(String[] args) throws Exception {
          Class.forName(
          "com.octetstring.jdbcLdap.sql.JdbcLdapDriver");
          String ldapConnectString
          = "jdbc:ldap://192.168.0.30/o=teemlink,c=cn?SEARCH_SCOPE:=subTreeScope";
          Connection con
          = DriverManager.getConnection(ldapConnectString, "cn=Manager,o=teemlink,c=cn", "secret");

          String sql
          = "SELECT * FROM ou=develop,o=teemlink,c=cn";

          Statement sat
          = con.createStatement();
          ResultSet rs
          = sta.executeQuery(sql);
          while (rs.next()) {
          System.out.println(rs.getString(
          1));
          }

          if (con != null)
          con.close();
          }
          }

           

          原創(chuàng)人員:Nicholas

           

           


          文章來源:http://www.cnblogs.com/obpm/archive/2010/08/28/1811065.html
          posted on 2010-08-28 14:38 obpm 閱讀(1932) 評論(0)  編輯  收藏 所屬分類: 架構(gòu)設(shè)計
          主站蜘蛛池模板: 雷山县| 来安县| 太谷县| 东明县| 同心县| 东至县| 湟中县| 教育| 邯郸县| 乃东县| 彭山县| 西华县| 衢州市| 锡林郭勒盟| 遂昌县| 苏尼特左旗| 常山县| 门源| 陇南市| 东海县| 彰化县| 鸡东县| 新宾| 开原市| 南川市| 讷河市| 红原县| 偏关县| 扶沟县| 白河县| 饶阳县| 郎溪县| 驻马店市| 增城市| 玛曲县| 贺兰县| 三江| 兴业县| 天等县| 青田县| 广宗县|