天天看點

LDAP入門

LDAP入門

  • 首先要先了解什麼是LDAP,當時我看了很多解釋,也是雲裡霧裡,弄不清楚。在這裡給大家稍微捋一捋。
  • 首先LDAP是一種通訊協定,LDAP支援TCP/IP。協定就是标準,并且是抽象的。在這套标準下,AD(Active Directory)是微軟出的一套實作。

    那AD是什麼呢?暫且把它了解成是個資料庫。也有很多人直接把LDAP說成資料庫(可以把LDAP了解成存儲資料的資料庫)。像是其他資料庫一樣,LDAP也是有client端和server端。server端是用來存放資源,client端用來操作增删改查等操作。

  • 而我們通常說的LDAP是指運作這個資料庫的伺服器。
  • 可以簡單了解AD =LDAP伺服器+LDAP應用。

那LDAP這種資料庫有什麼特殊的呢?

  • 我們知道,像MySQL資料庫,資料都是按記錄一條條記錄存在表中。而LDAP資料庫,是樹結構的,資料存儲在葉子節點上。看看下面的比喻:
假設你要樹上的一個蘋果(一條記錄),你怎麼告訴園丁它的位置呢?當然首先要說明是哪一棵樹(dc,相當于MYSQL的DB),然後是從樹根到那個蘋果所經過的所有“分叉”(ou),最後就是這個蘋果的名字(uid,相當于MySQL表主鍵id)。好了!這時我們可以清晰的指明這個蘋果的位置了,就是那棵“歪脖樹”的東邊那個分叉上的靠西邊那個分叉的再靠北邊的分叉上的半紅半綠的……,暈了!你直接爬上去吧!

就這樣就可以描述清楚“樹結構”上的一條記錄了。

說一下LDAP裡如何定義一個記錄的位置吧。

樹(dc=ljheee)
分叉(ou=bei,ou=xi,ou= dong)
蘋果(cn=redApple)
           

好了,redApple的位置出來了:

dn:cn=honglv,ou=bei,ou=xi,ou=dong,dc=ljheee

其中dn辨別一條記錄,描述了一條資料的詳細路徑。

咦!有人疑問,為什麼ou會有多個值?你想想,從樹根到達蘋果的位置,可能要經過好幾個樹杈,所有ou可能有多個值。關于dn後面一長串,分别是cn,ou,dc;中間用逗号隔開。

總結一下LDAP樹形資料庫如下:
dn :一條記錄的詳細位置
dc :一條記錄所屬區域    (哪一顆樹)
ou :一條記錄所屬組織    (哪一個分支)
cn/uid:一條記錄的名字/ID   (哪一個蘋果名字)
LDAP目錄樹的最頂部就是根,也就是所謂的“基準DN"。
           
  • 為什麼要用LDAP目錄樹來存儲資料,用MySQL不行嗎,為什麼非要搞出一個樹形的資料庫呢?
  • 這是因為用樹形結構存儲資料,查詢效率更高(具體為什麼,可以看一下關系型資料庫索引的實作原理——B樹/B+樹)。在某些特定的場景下,使用樹形資料庫更理想。比如:需要儲存大量的資料,而且資料不是經常更改,需要很快速的查找。
  • 把它與傳統的關系型資料庫相比,LDAP除了快速查找的特點,它還有很多的運用場景,比如域驗證等。

LDAP程式設計操作

  • 我們可以用JDBC操作MySQL資料庫,進行對資料的增删改查。同樣,LDAP樹形資料庫,也可以通過JDBC方式;除此之外,還可以用JNDI的方式(更推薦),因為樹形可以看做是目錄,樹結構的枝杈相當于目錄的層級。
  • 還有LDAP資料庫展示資料也是樹形的,如下圖是用ApacheDirectoryStudio連接配接的LDAP伺服器:
    LDAP入門
    image.png

可以把ApacheDirectoryStudio看做是連接配接資料庫伺服器的界面化的client,相當于Navicat、WorkBench。建立連接配接,連接配接資料庫伺服器的操作類似。

ApacheDirectoryStudio下載下傳位址

http://download.csdn.net/download/ljheee/10145654

JNDI連接配接LDAP伺服器

import org.springframework.beans.factory.annotation.Autowired;
import java.util.Hashtable;
import javax.naming.*;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;

public class LdapJNDI {

    @Autowired
    LdapConfiguration ldapConfiguration;

    public void JNDILookup() {
        String rootFilter = "o=cvte.com,o=isp";
//        String filter = "(&(smart-type=E1)(smart-status=1))";
        String filter = "(&(smart-type=E1)(uid=00012047))";
        String username = "uid=USER_NAME,ou=Authorization,ou=People,o=cc.com,o=isp";//xxx為申請的對接賬戶
        String password = "PASSW";

        Hashtable env = new Hashtable();
        env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");//設定連接配接LDAP的實作工廠
        env.put(Context.PROVIDER_URL, "ldap://172.26.39.77:389/" + rootFilter);// 指定LDAP伺服器的主機名和端口号
        env.put(Context.SECURITY_AUTHENTICATION, "simple");//給環境提供認證方法,有SIMPLE、SSL/TLS和SASL
        env.put(Context.SECURITY_PRINCIPAL, username);//指定進入的目錄識别名DN
        env.put(Context.SECURITY_CREDENTIALS, password); //進入的目錄密碼
        env.put("filter",filter);
        DirContext ctx = null;

        try {
            // 得到初始目錄環境的一個引用
            ctx = new InitialDirContext(env);

            //The search base entry 'uid=00012047,ou=Internal,ou=People,o=cvte.com,o=isp' does not exist]; remaining name 'uid=00012047,ou=Internal'
//            Attributes attrs = ctx.getAttributes("uid=00012047,ou=Internal,ou=People");//擷取到一個人員,


            NamingEnumeration bindings = ctx.listBindings("ou=Internal,ou=People");//列舉 内部人員

            while (bindings.hasMore()) {
                Binding bd = (Binding)bindings.next();
                System.out.println(bd.getName() + ": " + bd.getObject());
            }


             /*根據結點的DN來查找它的所有屬性, 然後再從屬性中得到所有的值,注意一個屬性可以有多個值*/
//            for (NamingEnumeration ae = attrs.getAll(); ae.hasMore(); ) {
//                //擷取一個屬性
//                Attribute attr = (Attribute) ae.next();
//                for (NamingEnumeration ve = attr.getAll(); ve.hasMore(); ) {
//                    System.out.println(String.format("Attribute=%s,Value=%s",attr.getID(),ve.next()) );
//                }
//            }

        } catch (javax.naming.AuthenticationException e) {
            System.out.println("認證失敗");
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("認證出錯:");
            e.printStackTrace();
        }finally {
            if (ctx != null) {
                try {
                    ctx.close();
                } catch (NamingException e) {
                    e.printStackTrace();
                }
            }
        }

    }

    public static void main(String[] args) {
        LdapJNDI ldapJNDI = new LdapJNDI();
        ldapJNDI.JNDILookup();

    }

}

           

最後總結一下LDAP:

1、LDAP的結構用樹來表示,而不是用表格。正因為這樣,就不能用SQL語句了。

2、LDAP可以很快地得到查詢結果,不過在寫方面,就慢得多。

3、LDAP提供了靜态資料的快速查詢方式。

4、Client/server模型,Server 用于存儲資料,Client提供操作目錄資訊樹的工具。

5、LDAP是一種開放Internet标準,LDAP協定是跨平台的Interent協定。

Spring LDAP的使用 Spring ldap ODM

Java反射實戰 操作ladp ODM

我的CSDN部落格 github位址