LDAP目錄服務器介紹

前言

本文介紹LDAP目錄服務器的簡單概念以及如何使用Java操做LDAP做目錄服務器java

正文

什麼是目錄服務器?

目錄是一個專門爲搜索和瀏覽而設計的數據庫,它也支持簡單的插入、刪除、修改功能。你能夠把它理解爲咱們傳統使用的關係型數據庫,可是他與咱們的關係型數據庫有着本質的區別,目錄的存儲結構相似於linux文件系統,他是一顆樹(相似下圖),因爲它是爲瀏覽和搜索而設計的,它的查詢速度很快,相反插入速度較慢,它也不支持事務和回滾以及複雜的插入、更新功能。目錄服務器可像關係型數據庫同樣對外提供數據服務,它能夠是單機或集羣式的。在集羣式的架構中每一個機器都擁有一致的數據備份。linux

樹中的每一個節點稱之爲條目(Entry),目錄服務是以條目爲基礎的,在上圖的樹型結構中,每一個條目都有一個惟一的絕對名字Directory Name(DN)和相對名字rDN。每一個條目具備一組屬性,每一個屬性有一個key,每一個key對應一個或多個value。具體每一個條目有哪些屬性由ObjectClass約束,也就是說每一個條目經過賦予ObjectClass來規定其必須擁有的屬性。git

例如上圖的babs條目中:數據庫

DN:uid=babs,ou=people,dc=example,dc=combash

相對於ou=people,dc=example,dc=com 節點的rDN:uid=babs服務器

ObjectClass:Person架構

什麼是LDAP?

LDAP全稱爲Lightweight Directory Access Protocol(輕量級目錄訪問協議),客戶端與目錄服務器遵循LDAP協議來發生交互,好比說新增一個節點,查詢某個節點的屬性等等。dom

常見的LDAP目錄服務器

與關係型數據庫同樣,LDAP目錄服務器是一個概念,包含許多具體實現的產品,好比關係型數據庫常見的有MySQL,Oracle等等。LDAP目錄服務器也有常見的具體實現,好比:OpenLDAP,Active Directory(Microsoft)。本文以OpenLDAP爲例介紹Java如何操做LDAP服務器。gitlab

何時使用LDAP目錄服務器?

看到目前爲止,你可能會以爲目錄服務器貌似和關係型數據庫服務器沒有什麼區別,到底何時該使用目錄服務器呢?ui

使用目錄服務器最多見的狀況就是多系統間的集中用戶管理,好比公司會使用OA,Confluence,gitlab,jira等等辦公系統。若是每一個系統都須要咱們記住一個帳號密碼,那無疑是很費力的。經過使用LDAP目錄服務器將多個應用的用戶集中管理起來,每一個應用都經過通用的LDAP協議與目錄服務器通訊,達到用戶信息集中管理的目的。事實上不少的開源項目都支持LDAP用戶認證(例如SuperSet,Hue等等)

代碼示例

package richstonedt.com;

import com.novell.ldap.*;
import com.novell.ldap.util.Base64;
import lombok.extern.slf4j.Slf4j;

import java.io.UnsupportedEncodingException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;


/**
 * 參考地址:http://www.micmiu.com/opensource/java-ldap-demo/
 */
@Slf4j
public class App {

    private static  String ldapHost = "192.168.x.x";
    private static int ldapPort = 389;
    private static String ldapBindDN = "cn=Manager,dc=my-domain,dc=com";
    private static String ldapPassword = "123456";
    private static int ldapVersion = LDAPConnection.LDAP_V3;

    /**
     * 獲取鏈接
     *
     * @return A LDAP Connection
     * @throws LDAPException
     * @throws UnsupportedEncodingException
     */
    @SuppressWarnings("deprecation")
    private static LDAPConnection connection() throws UnsupportedEncodingException, LDAPException {
        try {
            LDAPConnection lc = new LDAPConnection();
            //獲取鏈接
            lc.connect(ldapHost, ldapPort);
            //認證
            lc.bind(ldapVersion, ldapBindDN, ldapPassword.getBytes("UTF8"));
            log.info("鏈接LDAP服務器成功!");
            return lc;
        } catch (Exception e) {
            log.debug("LDAP服務器鏈接失敗!");
            throw e;

        }
    }

    /**
     * 搜索某目錄節點下全部節點及其屬性
     * @param DN 目錄節點名
     * @throws LDAPException
     * @throws UnsupportedEncodingException
     */
    public static void searchEntry(String DN) throws LDAPException, UnsupportedEncodingException {
        LDAPConnection conn = connection();
        try {
            LDAPSearchResults searchResults = conn.search(DN,
                    LDAPConnection.SCOPE_SUB, "objectClass=*", null, false);
            while (searchResults.hasMore()) {
                LDAPEntry nextEntry;
                try {
                    nextEntry = searchResults.next();
                } catch (LDAPException e) {
                    log.debug("Error: " + e);
                    if (e.getResultCode() == LDAPException.LDAP_TIMEOUT
                            || e.getResultCode() == LDAPException.CONNECT_ERROR) {
                        break;
                    } else {
                        continue;
                    }
                }
                log.info("DN :" + nextEntry.getDN());
                log.info("|---- Attributes list: ");
                LDAPAttributeSet attributeSet = nextEntry.getAttributeSet();
                Iterator<LDAPAttribute> allAttributes = attributeSet.iterator();
                while (allAttributes.hasNext()) {
                    LDAPAttribute attribute = allAttributes.next();
                    String attributeName = attribute.getName();

                    Enumeration<String> allValues = attribute.getStringValues();
                    if (null == allValues) {
                        continue;
                    }
                    while (allValues.hasMoreElements()) {
                        String value = allValues.nextElement();
                        if (!Base64.isLDIFSafe(value)) {
                            // base64 encode and then print out
                            value = Base64.encode(value.getBytes());
                        }
                        log.info("|---- ---- " + attributeName
                                + " = " + value);
                    }
                }
            }
        } finally {
            if (conn.isConnected()) {
                conn.disconnect();
            }
        }
    }

    /**
     * 新增一個目錄節點
     * @param baseDN
     * @param rDN
     * @param attribute
     * @throws UnsupportedEncodingException
     * @throws LDAPException
     */
    public static void addEntry(String baseDN, String rDN, Map<String, String> attribute) throws UnsupportedEncodingException, LDAPException {
        LDAPConnection conn = connection();
        try {
            LDAPAttributeSet attributeSet = new LDAPAttributeSet();
            for (Map.Entry<String, String> entry : attribute.entrySet()) {
                attributeSet.add(new LDAPAttribute(entry.getKey(), entry.getValue()));
            }
            String DN = rDN + "," + baseDN;
            conn.add(new LDAPEntry(DN, attributeSet));
        } finally {
            if (conn.isConnected())
                conn.disconnect();
        }
    }

    /**
     * 刪除一個目錄節點
     * @param DN 目錄節點名
     * @throws UnsupportedEncodingException
     * @throws LDAPException
     */
    public static void deleteEntry(String DN) throws UnsupportedEncodingException, LDAPException {
        LDAPConnection conn = connection();
        try {
            conn.delete(DN);
        } finally {
            if (conn.isConnected()) {
                conn.disconnect();
            }
        }

    }

    public static void main(String[] args) throws UnsupportedEncodingException, LDAPException {
        //新增節點
        Map<String, String> map = new HashMap<>();
        map.put("objectclass", "inetOrgPerson");
        map.put("cn", "liuruojing");
        map.put("sn", "liuruojing");
        addEntry("ou=userAccount,dc=my-domain,dc=com", "uid=liuruojing", map);

        //查詢節點
        searchEntry("uid=liuruojing,ou=userAccount,dc=my-domain,dc=com");

        //刪除節點
        deleteEntry("uid=liuruojing,ou=userAccount,dc=my-domain,dc=com");

    }


}
複製代碼

注意:須要引入JLDAP的Maven依賴

<dependency>
      <groupId>com.novell.ldap</groupId>
      <artifactId>jldap</artifactId>
      <version>4.3</version>
      <type>jar</type>
      <scope>compile</scope>
</dependency>
複製代碼
相關文章
相關標籤/搜索