ldap目錄服務
日常生活中,或者開發過程中,需要管理的目錄有很多。 如:人員組織管理,電話簿,地址簿,字典表等。
提供管理和查詢目錄信息的服務就是目錄服務。
有很多廠商實現了目錄服務,但是對外提供的接口不統一,所以客戶接入一個廠商之後想要切換廠商,成本很高。
所以出現了ldap 協議
ldap 協議規定所有的廠商對外提供接口的時候必須遵守統一的格式,
客戶端訪問也遵循統一的格式,這樣 之後,客戶端想要切換廠商只要 改一個地址就可以了。
特點
- 目錄服務的數據類型主要是字符型, 而不是關係數據庫提供的整數、浮點數、日期、貨幣等類型。爲了檢索的需要添加了BIN(二進制數據)、CIS(忽略大小寫)、CES(大小寫敏感)、TEL(電話型)等語法(Syntax)
- 同樣也不提供象關係數據庫中普遍包含的大量的函數
- 目錄有很強的查詢(讀)功能,適合於進行大量數據的檢索,但目錄一般只執行簡單的更新(寫)操作,不支持批量更新所需要的事務處理功能
- 它主要面向數據的查詢服務(查詢和修改操作比一般是大於10:1),不提供事務的回滾(rollback)機制.
- 目錄具有廣泛複製信息的能力,適合於多個目錄服務器同步/更新.
- LDAP目錄的結構用樹來表示,而不是用表格。正因爲這樣,就不能用SQL語句了
- LDAP目錄可以很快地得到查詢結果,不過在寫方面,就慢得多
- LDAP目錄提供了靜態數據的快速查詢方式
- LDAP 採用Client/server模型 Server 用於存儲數據 Client提供操作目錄信息樹的工具,這些工具可以將數據庫的內容以文本格式(LDAP 數據交換格式,LDIF)呈現在您的面前
爲什麼要用LDAP目錄樹來存儲數據,用MySQL不行嗎,爲什麼非要搞出一個樹形的數據庫呢?
- 是因爲用樹形結構存儲數據,查詢效率更高(具體爲什麼,可以看一下關係型數據庫索引的實現原理——B樹/B+樹)。在某些特定的場景下,使用樹形數據庫更理想。比如:需要儲存大量的數據,而且數據不是經常更改,需要很快速的查找。
- 把它與傳統的關係型數據庫相比,LDAP除了快速查找的特點,它還有很多的運用場景,比如域驗證等。
LDAP目錄數據結構
在LDAP中目錄是按照樹型結構組織——目錄信息樹(DIT)
DIT是一個主要進行讀操作的數據庫 DIT由條目(Entry)組成,條目相當於關係數據庫中表的記錄;
條目是具有分辨名DN(DistinguishedName)的屬性-值對(Attribute-value,簡稱AV)的集合.
LDIF是LDAP數據庫信息的一種文本格式。
1. LDAP簡介
LDAP(輕量級目錄訪問協議,Lightweight Directory Access Protocol)是實現提供被稱爲目錄服務的信息服務。目錄服務是一種特殊的數據庫系統,其專門針對讀取,瀏覽和搜索操作進行了特定的優化。目錄一般用來包含描述性的,基於屬性的信息並支持精細複雜的過濾能力。目錄一般不支持通用數據庫針對大量更新操作操作需要的複雜的事務管理或回捲策略。而目錄服務的更新則一般都非常簡單。這種目錄可以存儲包括個人信息、web鏈結、jpeg圖像等各種信息。爲了訪問存儲在目錄中的信息,就需要使用運行在TCP/IP 之上的訪問協議—LDAP。
LDAP目錄中的信息是是按照樹型結構組織,具體信息存儲在條目(entry)的數據結構中。條目相當於關係數據庫中表的記錄;條目是具有區別名DN (Distinguished Name)的屬性(Attribute),DN是用來引用條目的,DN相當於關係數據庫表中的關鍵字(Primary Key)。屬性由類型(Type)和一個或多個值(Values)組成,相當於關係數據庫中的字段(Field)由字段名和數據類型組成,只是爲了方便檢索的需要,LDAP中的Type可以有多個Value,而不是關係數據庫中爲降低數據的冗餘性要求實現的各個域必須是不相關的。LDAP中條目的組織一般按照地理位置和組織關係進行組織,非常的直觀。LDAP把數據存放在文件中,爲提高效率可以使用基於索引的文件數據庫,而不是關係數據庫。類型的一個例子就是mail,其值將是一個電子郵件地址。
LDAP的信息是以樹型結構存儲的,在樹根一般定義國家(c=CN)或域名(dc=com),在其下則往往定義一個或多個組織 (organization)(o=Acme)或組織單元(organizational units) (ou=People)。一個組織單元可能包含諸如所有僱員、大樓內的所有打印機等信息。此外,LDAP支持對條目能夠和必須支持哪些屬性進行控制,這是有一個特殊的稱爲對象類別(objectClass)的屬性來實現的。該屬性的值決定了該條目必須遵循的一些規則,其規定了該條目能夠及至少應該包含哪些屬性。例如:inetorgPerson對象類需要支持sn(surname)和cn(common name)屬性,但也可以包含可選的如郵件,電話號碼等屬性。
2. LDAP簡稱對應
o– organization(組織-公司)可以 3~64 個字符長度。
ou – organization unit(組織單元-部門) 最多可以有四級,每級最長 32 個字符,可以爲中文。
c - countryName(國家)
dc - domainComponent(域名)dc=xxxx,dc=com
sn – suer name(真實名稱)
cn - common name(常用名稱)最長可以到 80 個字符,可以爲中文。
dn 類似於 Linux 文件系統的絕對路徑,每個對象都有一個唯一的名稱。
3. 目錄設計
LDAP 目錄樹的最頂部就是根,也就是所謂的 " 基準DN "。
基準 DN 通常使用三種格式之一
- 以 X.500 格式表示的基準 DN,例如 o=xxxx, c=CN
- 用公司的 Internet 地址表示的基準 DN,例如 o=xxxx.com
- 用 DNS 域名的不同部分組成的基準 DN,例如 dc=xxxx, dc=com
- 如果使用活動目錄(Active Directory),Microsoft 限制必須使用 DNS 域名格式。
設計目錄結構是LDAP最重要的方面之一。下面我們將通過一個簡單的例子來說明如何設計合理的目錄結構。該例子將通過Netscape地址薄來訪文。假設有一個位於美國US(c=US)而且跨越多個州的名爲Acme(o=Acme)的公司。Acme希望爲所有的僱員實現一個小型的地址薄服務器。
我們從一個簡單的組織DN開始:
dn: o=Acme, c=US
Acme所有的組織分類和屬性將存儲在該DN之下,這個DN在該存儲在該服務器的目錄是唯一的。Acme希望將其僱員的信息分爲兩類:管理者(ou= Managers)和普通僱員(ou=Employees),這種分類產生的相對區別名(RDN,relative distinguished names。表示相對於頂點DN)就shi :
dn: ou=Managers, o=Acme, c=US
dn: ou=Employees, o=Acme, c=US
在下面我們將會看到分層結構的組成:頂點是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。然後將前面的父條目結合在一起就形成如下的樹型結構:
cn=Jason H. Smith
+ ou=Managers
+ o=Acme
+ c=US
-> dn: cn=Jason H. Smith,ou=Managers,o=Acme,c=US
現在已經定義好了目錄結構,下一步就需要導入目錄信息數據。目錄信息數據將被存放在LDIF文件中,其是導入目錄信息數據的默認存放文件。用戶可以方便的編寫Perl腳本來從例如/etc/passwd、NIS等系統文件中自動創建LDIF文件。
下面的實例保存目錄信息數據爲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: [email protected]
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: [email protected]
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: [email protected]
localityName:Houston
4 定製對象
- LDAP 目錄可以定製成存儲任何文本或二進制數據。
- LDAP 目錄用對象類型(object classes)的概念來定義運行哪一類的對象使用什麼屬性。
- LDAP 目錄以一系列 " 屬性對 " 的形式來存儲記錄項,每一個記錄項包括屬性類型和屬性值(這與關係型數據庫用行和列來存取數據有根本的不同)。
- LDAP 目錄被設計成爲一個屬性保存多個值的,而不是在每一個屬性的後面用逗號把一系列值分開。這樣的方式存儲數據,數據庫有很大的靈活性,不必爲加入一些新的數據就重新創建表和索引。
- LDAP 目錄不必花費內存或硬盤空間處理 " 空 " 域,也就是說,實際上不使用可選擇的域也不會花費任何資源。
- 記錄項的格式是 LDIF,用來導入和導出 LDAP 目錄的記錄項。
- 屬性的值在保存的時候是保留大小寫的,但是在默認情況下搜索的時候是不區分大小寫的。
- 某些特殊的屬性(例如,password)在搜索的時候需要區分大小寫。
5 模式
Schema是LDAP的一個重要組成部分,類似於數據庫的模式定義,LDAP的Schema定義了LDAP目錄所應遵循的結構和規則,比如一個 objectclass會有哪些屬性,這些屬性又是什麼結構等等,schema給LDAP服務器提供了LDAP目錄中類別,屬性等信息的識別方式,讓這些可以被LDAP服務器識別。
在LDAP的schema中,有四個重要的元素:
1、Objectclass
objectclass定義了一個類別,這個類別會被不同的目錄(在LDAP中就是一個Entry)用到,它說明了該目錄應該有哪些屬性,哪些屬性是必須的,哪些又是可選的。一個objectclass的定義包括名稱(NAME),說明(DESC),類型(STRUCTURAL或AUXILARY ,表示是結構型的還是輔助型的),必須屬性(MUST),可選屬性(MAY)等信息。
例如:
這裏kunmailUser這種數據,要包含maildir $home $clearpw $forwardAddr $quota $storeHost $delivery $mailReplyText $active等可選項,還要包括username $cn $vuid $vgid 必選項。 可選項用MAY()來包含,必選項用MUST()來包含。DESC是說明項。SUP表示父類(有點像面向對象編程啊)top表示沒有父類,他自己是頂級。STRUCTURAL是存儲方式。一般來說每個節點都要包含一個ABSTRACT類("top" or "alias"), 至少一個STRUCTURAL類,0個或者多個AUXILIARY類。AUXILIARY表示輔助型、STRUCTURAL表示結構型(默認)、ABSTRACT表示摘要型。
下面定義一個允許將myPhoto增加到任何已經存在的條目中的auxiliary對象類:
如果您的組織需要一個私有的結構化對象類來表示用戶,你可以子類化任何一個已經存在的person類,比如inetOrgPerson(RFC2798),然後增加需要的屬性:
該對象類從inetOrgPerson中繼承允許的或者必須的屬性,但是,要求myUniqueName和givenName,允許myPhoto。
2、Attribute
attribute就是一個上面objectclass中可能包含的屬性,對其的定義包括名稱,數據類型,單值還是多值以及匹配規則等。後面用具體的例子來說明。
Attribute格式:
whsp是空格的意思(' ')。numericoid 是全局唯一的 OID,是帶.的十進制形式 (e.g. 1.1.0), qdescrs有一個或幾個意思, woid 可以使名稱或者是 OID 可選擇的一定長度的後綴(e.g {10})。
例如,屬性類型name和cn在core.schema中如下定義:
請注意,每一個都定義了屬性的OID,給出了一個短的名稱,以及一個簡短的描述。每一個名稱都是OID的一個別名。Slapd(8)在返回結果的時候,將返回第1個列出的名稱。
第1個名稱,name,保存了directoryString(UTF-8編碼的Unicode)語法。該語法由OID說明。(1.3.6.1.4.1.1466.115.121.1.15標識了目錄字符串語法)。還說明了一個推薦長度爲32768的選項。服務器應該支持該長度的值,但是,也可以支持更長的值。該域沒有指明長度限制,因此,在服務器上被忽略,並且服務器不會限制其大小。另外,相等和子串匹配使用不區分大小寫的規則。下面是經常使用的語法和匹配規則(OpenLDAP支持這些,以及更多)
第2個屬性,cn,是name的一個子類型,因此,它繼承了語法,匹配規則,並且使用name.commonName作爲別名。
兩個屬性都沒有限制到單一值。都可以被用戶應用程序所使用,都不存在過期,都不是集合。
很多組織爲用戶保留唯一的名字(unique name),雖然用戶可以使用displayName,但是這個屬性(name)依舊由用戶控制。而不是organization。我們可以從 inetorgperson.schema 拷貝displayName ,替換OID,name,和描述(description)。
但是,如果我們要使name屬性包含一個斷言,這個屬性可以被定義爲name的子屬性。
很多的組織爲每一個用戶保留一個頭像。myPhoto屬性類型的定義可以用來保存用戶的頭像。當然用戶可以選擇jpegPhoto屬性類型(RFC2798)(或其子類型)來保存頭像。當然你只能在圖片符合JPEG File Interchange Format時使用。
當然,一個使用八進制語法的屬性類型可以這樣的定義:
在這,語法中並沒有置頂photo的格式(format),這裏假設訪問屬性的應用可以對其值進行處理。
如果你想支持多種圖片格式,你需要爲每一個格式定義屬性類型。爲圖片添加類型信息的前綴。或者使用ASN.1描述值,和use the ;binary transfer option。
可以使圖片屬性能夠保存URI,你可以在labeledURI(RFC2079)後創建一個屬性,或者創建一個子類型。
3、Syntax
syntax是LDAP中的“語法”,其實就是LDAP中會用到的數據類型和數據約束,這個語法是遵從X.500中數據約束的定義的。其定義需要有一個ID(遵從X.500)以及說明(DESP)
4、Matching Rules
是用來指定某屬性的匹配規則,實際上就是定義一個特殊的Syntax的別名,讓LDAP服務器可以識別,並對定義的屬性進行匹配。
LDAP的schema的主要元素就是這些了,下面列舉出了一些LDAP規定好的或是現在比較通用的schema,一般的LDAP服務器都應該可以識別這些定義。
這就是一個名爲subschema的objectclass的定義:
首先是ID,這裏是2.5.20.1,接着是NAME,AUXILIARY說明是輔助型,之後是可選屬性的定義,subschema中沒有定義必須屬性,如果需要定義,應該和MAY一樣,將屬性放在MUST()中並用$隔開
再來看一個屬性定義:
可以看到cn屬性的父屬性是name,它相等性匹配於caseIgnoreMatch(匹配原則爲EQUALITY,還有如SUBSTR是字符串匹配,ORDERING是順序匹配)
syntax定義一般都比較簡單,如:
這個定義說明,這一串數字1.3.6.1.4.1.1466.115.121.1.5就代表了LDAP中的字符串,這個數字串的定義和X.500相關,包括了它的存儲方式,所佔空間大小等。
最後看看Matching Rule的例子,前面提到了caseIgnoreMatch,就看他的吧
其實1.3.6.1.4.1.1466.115.121.1.15 就是LDAP數據類型Directory String的ID,說明前面的cn需要等於這個數據類型纔有效。
還有很多常用schema的定義都在了RFC2252中,LDAP服務器都應該支持這些基本的schema。
命名目錄服務的功能有哪些?
支持四類10種操作:
查詢類 : 搜索 ,比較
更新類: 添加 修改條目,修改條目名, 刪除
認證類: 綁定,解綁定
其他類:放棄 ,擴展。
命名目錄服務可以解決什麼問題
- 1.LDAP目錄服務可以有效地解決衆多網絡服務的用戶賬戶問題。實現集中賬號管理
- 2.LDAP目錄服務規定了統一的身份信息數據庫、身份認證機制和接口,實現了資源和信息的統一管理,保證了數據的一致性和完整性。
- 3.LDAP目錄服務是以樹狀的層次結構來描述數據信息的,此種模型適應了衆多行業應用的業務組織結構。
常用的命名服務器有哪些?
廠商 |
產品 |
介紹 |
SUN |
SUNONE Directory Server |
基於文本數據庫的存儲,速度快 。 |
IBM |
IBM Directory Server |
基於DB2 的的數據庫,速度一般。 |
Novell |
Novell Directory Server |
基於文本數據庫的存儲,速度快, 不常用到。 |
Microsoft |
Microsoft Active Directory |
基於WINDOWS系統用戶,對大數據量處理速度一般,但維護容易,生態圈大,管理相對簡單。 |
Opensource |
Opensource |
OpenLDAP 開源的項目,速度很快,但是非主 流應用。 |
OpenLDAP 目錄服務優點
OpenLDAP 目錄服務有以下10 個優點。
OpenLDAP 是一個跨平臺的標準互聯網協議,它基於X.500 標準協議。
OpenLDAP 提供靜態數據查詢搜索,不需要像在關係數據中那樣通過SQL 語句維護數據庫信息。
OpenLDAP 基於推和拉的機制實現節點間數據同步,簡稱複製(replication)並提供基於TLS、SASL 的安全認證機制,實現數據加密傳輸以及Kerberos 密碼驗證功能。
OpenLDAP 可以基於第三方開源軟件實現負載(LVS、HAProxy)及高可用性解決方案,24 小時提供驗證服務,如Headbeat、Corosync、Keepalived 等。
OpenLDAP 數據元素使用簡單的文本字符串(簡稱LDIF 文件)而非一些特殊字符,便於維護管理目錄樹條目, 章
OpenLDAP 可以實現用戶的集中認證管理,所有關於賬號的變更,只須在OpenLDAP 服務器端直接操作,無須到每臺客戶端進行操作,影響範圍爲全局。
OpenLDAP 默認使用協議簡單如支持TCP/ZP 協議傳輸條目數據,通過使用查找操作實現對目錄樹條目信息的讀寫操作,同樣可以通過加密的方式進行獲取目錄樹條目信息。
OpenLDAP 產品應用於各大應用平臺(Nginx、HTTP、vsftpd、Samba、SVN、Postfix、OpenStack、Hadoop 等)、服務器(HP、IBM、Dell 等)以及存儲(EMC、NetApp 等)控制檯,負責管理賬號驗證功能,實現賬號統一管理。
OpenLDAP 實現具有費用低、配置簡單、功能強大、管理容易及開源的特點。
OpenLDAP 通過ACL(Access Control List)靈活控制用戶訪問數據的權限,從而保證數據的安全性。
OpenLDAP 功能
在LDAP 的功能模型中定義了一系列利用LDAP 協議的操作,主要包含以下4 部分。
查詢操作(ldapsearch):允許查詢目錄並取得條目,其查詢性能比關係數據庫好。
更新操作(ldapupdate):目錄樹條目支持條目的添加、刪除、修改等操作。
同步操作:OpenLDAP 是一種典型的分佈式結構,提供複製同步,可將主服務器上的數據通過推或拉的機制實現在從服務器上更新,完成數據的同步,從而避免OpenLDAP 服務器出現單點故障,影響用戶驗證。
認證和管理操作:允許客戶端在目錄中識別自己,並且能夠控制一個會話的性質。
OPENLDAP 服務器
環境:基於centos7,OpenLDAP使用2.4.44版本
安裝
使用命令安裝OpenLDAP:
yum -y install openldap compat-openldap openldap-clients openldap-servers openldap-servers-sql openldap-devel migrationtools
查看OpenLDAP版本,使用如下命令:
slapd -VV
OpenLDAP配置
OpenLDAP2.4.23版本開始所有配置數據都保存在/etc/openldap/slapd.d/
配置OpenLDAP管理員密碼
slappasswd -s [password]
密碼設置好了之後呢,保存好,下面會使用到。
修改olcDatabase={2}hdb.ldif文件
修改olcDatabase={2}hdb.ldif文件,對於該文件增加一行
olcRootPW: {SSHA}dXgO/Ipy5SQiKFZ0u7m79Xo7uzKIr038,然後修改域信息:
olcSuffix: dc=teracloud2,dc=cn
olcRootDN: cn=admin,dc=teracloud2,dc=cn
注意:其中cn=admin中的admin表示OpenLDAP管理員的用戶名,dc爲ldap的服務器域名,導出而olcRootPW表示OpenLDAP管理員的密碼。
實際修改如下:
vim /etc/openldap/slapd.d/cn=config/olcDatabase\=\{2\}hdb.ldif
olcSuffix: dc=teracloud2,dc=cn
olcRootDN: cn=admin,dc=teracloud2,dc=cn
olcRootPW: {SSHA}dXgO/Ipy5SQiKFZ0u7m79Xo7uzKIr038
修改olcDatabase={1}monitor.ldif文件
修改olcDatabase={1}monitor.ldif文件,如下:
vim /etc/openldap/slapd.d/cn=config/olcDatabase\=\{1\}monitor.ldif
olcAccess: {0}to * by dn.base=”gidNumber=0+uidNumber=0,cn=peercred,cn=extern
al,cn=auth” read by dn.base=”cn=admin,dc=teracloud2,dc=cn” read by * none
驗證OpenLDAP的基本配置是否正確,使用如下命令:
slaptest -u
通過結果看出我們的配置是沒有問題的
啓動OpenLDAP服務
//開始ldap
systemctl enable slapd
//啓動ldap
systemctl start slapd
//查看ldap的狀態
systemctl status slapd
配置OpenLDAP數據庫
OpenLDAP默認使用的數據庫是BerkeleyDB,現在來開始配置OpenLDAP數據庫,使用如下命令:
cp /usr/share/openldap-servers/DB_CONFIG.example /var/lib/ldap/DB_CONFIG
chown ldap:ldap -R /var/lib/ldap
chmod 700 -R /var/lib/ldap
ll /var/lib/ldap/
注意:/var/lib/ldap/就是BerkeleyDB數據庫默認存儲的路徑。
導入基本Schema
導入基本Schema,使用如下命令:
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/cosine.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/nis.ldif
ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/openldap/schema/inetorgperson.ldif
注意:如果這一步導入失敗,一般都是密碼輸入錯誤,密碼要輸上面配置的加密前的密碼
創建基本的用戶節點,數據庫管理員
dn: dc=teracloud2,dc=cn
objectClass: top
objectClass: dcObject
objectclass: organization
o: Example Inc.
dc: teracloud2
dn: ou=Users,dc=teracloud2,dc=cn
objectClass: organizationalUnit
ou: Users
dn: ou=group,dc=teracloud2,dc=cn
objectClass: organizationalUnit
ou: group
dn: cn=admin,dc=teracloud2,dc=cn
objectClass: organizationalRole
cn: admin
description: Directory Administrator
ldapadd -x -D cn=admin,dc=teracloud2,dc=cn-W -f basedomain.ldif
[root@VM_0_15_centos myself]# ldapadd -x -D cn=admin,dc=teracloud2,dc=cn-W -f basedomain.ldif
Enter LDAP Password:
adding new entry “dc=teracloud2,dc=cn”
adding new entry “ou=people,dc=teracloud2,dc=cn”
adding new entry “ou=group,dc=teracloud2,dc=cn”
adding new entry “cn=admin,dc=teracloud2,dc=cn”
配置日誌
[root@VM_0_15_centos myself]# vim log.ldif
[root@VM_0_15_centos myself]# cat log.ldif
dn: cn=config
changetype: modify
add: olcLogLevel
olcLogLevel: 32
"log.ldif" [New] 4L, 66C written
[root@VM_0_15_centos myself]# ldapmodify -Y EXTERNAL -H ldapi:/// -f log.ldif
SASL/EXTERNAL authentication started
SASL username: gidNumber=0+uidNumber=0,cn=peercred,cn=external,cn=auth
SASL SSF: 0
modifying entry "cn=config"
[root@VM_0_15_centos myself]# mkdir -p /var/log/slapd
[root@VM_0_15_centos myself]# chown ldap:ldap /var/log/slapd/
[root@VM_0_15_centos myself]# echo "local4.* /var/log/slapd/slapd.log" >> /etc/rsyslog.conf
[root@VM_0_15_centos myself]# systemctl restart rsyslog
[root@VM_0_15_centos myself]# systemctl restart slapd
[root@VM_0_15_centos myself]# tail -n 4 /var/log/slapd/slapd.log
Sep 5 20:43:31 VM_0_15_centos slapd[4520]: => test_filter
Sep 5 20:43:31 VM_0_15_centos slapd[4520]: PRESENT
Sep 5 20:43:31 VM_0_15_centos slapd[4520]: <= test_filter 6
Sep 5 20:43:31 VM_0_15_centos slapd[4523]: slapd starting
工具連接
圖形操作界面有很多種,包括ldapadmin、ldapadmin.exe,當然還有其他的,這個步驟比較簡單,就不詳細講解了
遇到的錯誤
查看ldap的狀態,發現無法啓動
查看日誌發現,有個和證書相關的錯誤
could not use certificate openLDAP server’,
查看下目錄發現沒有證書的,目錄
把證書拷貝過去,啓動,問題解決
客戶端訪問:
1 可以把ApacheDirectoryStudio看做是連接數據庫服務器的界面化的client,相當於Navicat、WorkBench。新建連接,連接數據庫服務器的操作類似。
ApacheDirectoryStudio下載地址
http://download.csdn.net/download/ljheee/10145654
2 可以用JDBC操作MySQL數據庫,進行對數據的增刪改查。同樣,LDAP樹形數據庫,也可以通過JDBC方式;除此之外,還可以用JNDI的方式(更推薦),因爲樹形可以看做是目錄,樹結構的枝杈相當於目錄的層級。
JNDI :全稱:JAVA NAMING AND Directory interface
解釋:java 命名目錄訪問接口:java 命名服務和目錄服務而提供的統一API。
理解:通過命名來訪問需要的資源,類似DNS服務,可通過 key-value的形式。
JNDI是JAVA爲命名及目錄服務訪問制定的基礎接口標準,用於訪問包括DNS,NIS,LDAP,文件系統等任何以樹目錄形式存在目標對象,並且基本上可保持訪問方式的一致(意味着代碼共用)。對於不同的目錄類型,JNDI通過使用不同的目錄驅動,以保證訪問方式的一致
LDAP :全稱:LIGHTWEIGHT DIRECTORY ACCESS Protocol
解釋: 輕量級目錄訪問協議。是在20世紀90年代早期作爲標準目錄協議進行開發的。它是目前最流行的目錄協議,與廠商、具體平臺無關。LDAP用統一的方式定義瞭如何訪問目錄服務中的內容,比如增加、修改、刪除一個條目
理解:LDAP用統一的方式定義瞭如何訪問目錄服務中的內容,比如增加、修改、刪除一個條目。
LDAP 是協議,LDAP 服務可以理解爲“層次數據庫”服務,相比關係型數據庫,查詢更快。
關係JNDI - LDAP :
JNDI則是Java中用於訪問LDAP的API,開發人員使用JNDI完成與LDAP服務器之間的通信,即用JNDI來訪問LDAP,而不需要和具體的目錄服務產品特性打交道。這樣通過LDAP、JNDI兩層抽象,使Java程序對目錄服務的訪問做到了平臺無關性。
連接:
Hashtable env = new Hashtable();
String LDAP_URL = "ldap://<IP>:389"; // LDAP 訪問地址
String adminName = "example\\user"; // 注意用戶名的寫法:domain\User 或 cn=user
String adminPassword = "userpassword"; // 密碼
env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, LDAP_URL);
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, adminName);
env.put(Context.SECURITY_CREDENTIALS, adminPassword);
try {
dc = new InitialDirContext(env);// 初始化上下文
System.out.println("認證成功");
} catch (javax.naming.AuthenticationException e) {
System.out.println("認證失敗");
} catch (Exception e) {
System.out.println("認證出錯:" + e);
}
增加記錄
String root = "dc=example,dc=com"; // LDAP的根節點的DC
BasicAttributes attrs = new BasicAttributes();
BasicAttribute objclassSet = new BasicAttribute("objectClass");
objclassSet.add("sAMAccountName");
objclassSet.add("employeeID");
objclassSet.add("sAMAccountName");
objclassSet.add("employeeID");
attrs.put(objclassSet);
attrs.put("ou", newUserName);
dc.createSubcontext("ou=" + newUserName + "," + root, attrs);
LDAP 刪除記錄
try {
dc.destroySubcontext(dn);
} catch (Exception e) {
e.printStackTrace();
System.out.println("Exception in delete():" + e);
}
修改記錄
try {
ModificationItem[] mods = new ModificationItem[1];
/* 修改屬性 */
// Attribute attr0 = new BasicAttribute("employeeID", "test");
// mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr0);
/* 刪除屬性 */
// Attribute attr0 = new BasicAttribute("description", "test");
// mods[0] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE, attr0);
/* 添加屬性 */
Attribute attr0 = new BasicAttribute("employeeID", employeeID);
mods[0] = new ModificationItem(DirContext.ADD_ATTRIBUTE, attr0);
/* 修改 */
dc.modifyAttributes(dn + ",dc=example,dc=com", mods);
return true;
} catch (NamingException e) {
e.printStackTrace();
System.err.println("Error: " + e.getMessage());
return false;
}
重命名
try {
dc.rename(oldDN, newDN);
return true;
} catch (NamingException ne) {
System.err.println("Error: " + ne.getMessage());
return false;
}
查詢
// 創建搜索控件
SearchControls searchCtls = new SearchControls();
// 設置搜索範圍
searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
// 設置搜索過濾條件
String searchFilter = "sAMAccountName=" + userName;
// 設置搜索域節點
String searchBase = "DC=example,DC=COM";
// 定製返回屬性
String returnedAtts[] = { "url", "whenChanged", "employeeID", "name", "userPrincipalName", "physicalDeliveryOfficeName", "departmentNumber", "telephoneNumber", "homePhone", "mobile", "department", "sAMAccountName", "whenChanged", "mail" };
// 不定製屬性,返回所有的屬性集
// searchCtls.setReturningAttributes(null);
int totalResults = 0;
try {
NamingEnumeration answer = dc.search(searchBase, searchFilter, searchCtls);
while (answer.hasMoreElements()) {
SearchResult sr = (SearchResult) answer.next();
Attributes Attrs = sr.getAttributes();
if (Attrs != null) {
try {
for (NamingEnumeration ne = Attrs.getAll(); ne.hasMore();) {
Attribute Attr = (Attribute) ne.next();
// 讀取屬性值
for (NamingEnumeration e = Attr.getAll(); e.hasMore(); totalResults++) {
// 接受循環遍歷讀取的userPrincipalName用戶屬性
String user = e.next().toString();
}
// 讀取屬性值
// Enumeration values = Attr.getAll();
// if (values != null) {
// while (values.hasMoreElements()) {
// System.out.println(" 2AttributeValues=" + values.nextElement());
// }
// }
}
} catch (NamingException e) {
System.err.println("Throw Exception : " + e);
}
}
}
} catch (Exception e) {
e.printStackTrace();
System.err.println("Throw Exception : " + e);
}
搜索範圍包含
- 本節點:SearchControls.OBJECT_SCOPE
- 單層:SearchControls.ONELEVEL_SCOPE
- 遍歷:SearchControls.SUBTREE_SCOPE
LDAP 關閉
if (dc != null) {
try {
dc.close();
} catch (NamingException e) {
System.out.println("NamingException in close():" + e);
}
}