在本文中,學習如何使用 Net::LDAP 庫在 IBM® Tivoli® Directory Server V6.0 目錄伺服器創建一個 LDAP 目錄服務,親歷用 Net::LDAP Ruby 庫添加、修改、搜索和刪除目錄項的各個示例。以 Tivoli Directory Server V6.0 作為後端資料庫創建一個 Ruby on Rails 應用程序。
簡介
Tivoli Directory Server 是一個基於 LDAP V3 的目錄伺服器,可用來創建目錄服務。所謂的目錄服務是指一個能存儲、檢索和修改網路資源信息的應用程序。LDAP 是一種用於訪問目錄服務的輕量協議,建立在目錄項的基礎之上。一個項是一組屬性,由全局惟一的專有名稱(DN)標識。每個目錄項屬性都具有一個類型和一個或多個值。在本文中,學習如何使用 Net::LDAP 庫在 Tivoli Directory Server V6.0 目錄伺服器創建一個 LDAP 目錄服務,用 Tivoli Directory Server V6.0 作為後端資料庫創建一個 Ruby on Rails 應用程序。
先決條件和系統需求
本文要求您對 LDAP 和腳本語言有基本的理解。本文主要面向的是對 LDAP 有基本認識並需要使用 Ruby 腳本語言編寫目錄服務的讀者。為了進行本文中的示例操作,必須要安裝 Tivoli Directory Server V6.0。下載 本文中的這個示例 LDAP 應用程序。
有關 Ruby on Rails
Ruby on Rails 是一種開源 Web 框架,用於基於資料庫開發 Web 應用程序。Ruby on Rails 提供了開發的簡便性、對 Ajax 的支持以及 Model-View-Controller(MVC)框架。Ruby 是一種解釋性的、面向對象的腳本語言。解釋性 意味著 Ruby 應用程序的運行無需首先對之進行編譯。Ruby 內的變數不具有類型;一個 Ruby 變數可以包含任何類型的數據。Ruby 內的變數也無需變數聲明。作為一種面向對象的語言,Ruby 具有諸如類、方法和繼承之類的特性。
要開發一個 Ruby on Rails 應用程序,必須具備 Web 伺服器和資料庫。Rails 包括一個內置的 Web 伺服器,稱為 WEBrick。Rails 默認配置有 MySQL 資料庫。Rails 是如下這些子項目的綜合。
模型提供數據,控制器提供業務邏輯來處理數據,視圖展示數據。
MVC Rails 應用程序包含如下的 Ruby、RHTML 和配置文件:
Ruby on Rails 提供用來生成模型和控制器腳本的命令。常用的 Ruby on Rails 命令如下所示。
命令(變數以斜體表示) | 描述 |
---|---|
rails applicationname | 創建具有特定名稱的 Rails 應用程序 |
ruby script/server | 啟動 http://localhost:3000 處的 Ruby Rails Web 伺服器 WEBrick |
ruby script/generate model modelname | 生成具有特定模型名的一個 model 類 |
ruby script/generate controller controllername controlleraction1 controlleraction2 ... | 生成具有特定名稱的一個 controller 類,如指定,還會生成控制器動作;還會生成對應於控制器動作的 view 模板(.rhtml 文件) |
Ruby on Rails 提供各種 Ruby 庫來開發 LDAP 應用程序。比如:
在本文中,您將學習使用 Net::LDAP 庫在 Tivoli Directory Server V6.0 目錄伺服器內創建一個目錄服務。此外,您還將使用 Net::LDAP Ruby 庫添加、修改、搜索和刪除一個目錄項。
安裝
本節展示如何安裝 Rails 框架 Ruby 以及 RubyGems。RubyGems 是標準的 Ruby 包管理器,與 Ruby 應用程序和庫聯合使用。此外,您還將安裝 Net::LDAP,它是面向 LDAP 的 Ruby 類庫。示例應用程序使用的是 Windows® 平台。安裝的順序是先安裝 Ruby,然後安裝 Rails,最後安裝 Net::LDAP。
基本的 Ruby 安裝
要安裝 Ruby 和 RubyGems 的最新版本:
Rails
安裝 Rails:
Net::LDAP 包
用如下代碼安裝 ruby-net-ldap gem:
C:/ruby>gem install ruby-net-ldap |
Net::LDAP 類提供了 LDAP 客戶機協議的一種 Ruby 實現。Net::LDAP 類可被用來進行綁定、搜索、添加、修改、刪除和重命名操作。Net::LDAP 類方法如表 2 所示。
方法 | 描述 |
---|---|
add(args) | 添加一個新目錄項。參數為:
|
add_attribute(dn, attribute, value) | 向屬性添加一個值。如果所指定的屬性還沒有定義,就會創建一個新屬性。 |
authenticate(username, password) | 指定 LDAP 伺服器的身份驗證憑證。 |
bind(auth=@auth) | 連接到 LDAP 伺服器並基於在 open 或 new 方法內指定的身份驗證憑證請求身份驗證。如果與 LDAP 伺服器的連接建立,就會返回 true。 |
bind_as(args={}) | 作為一個指定用戶綁定。 |
delete(args) | 針對指定的 DN 刪除目錄項,DN 是所支持的惟一參數。 |
delete_attribute(dn, attribute) | 刪除一個屬性及其所有值。dn 參數指定此目錄項,attribute 參數指定要刪除的那個屬性。 |
get_operation_result() | 返回綁定、搜索、添加、修改、重命名和刪除操作的操作結果代碼和消息。 |
modify(args) | 修改指定目錄項的屬性值。將如下參數作為一個 hash:
|
new(args = {}) | 創建類型 Net::LDAP 的一個對象,但不會打開與伺服器的連接。參數可以是:
|
創建一個 Rails 應用程序
在本節內,創建一個 Rails 應用程序來用 Net::LDAP Ruby 庫創建一個目錄服務。使用 rails 命令來創建一個稱為 netldap 的 rails 應用程序:
c:/ruby>rails netldap |
一個具有 Rails 應用程序完整目錄結構的 Rails 應用程序將被創建。我們將作為一個控制器腳本運行這個 Net::LDAP Ruby on Rails 應用程序,來用不同的控制器動作分別創建一個目錄項、修改一個目錄項、搜索一個目錄項和刪除一個目錄項。此外還將對應於每個控制器動作創建 RHTML 視圖模板以便為目錄項輸入數據。
創建一個稱為 directory 的控制器腳本,包含控制器動作 add_entry、modify_entry、 search_entry 和 delete_entry:
C:/ruby/netldap>ruby script/generate controller directory add_entry modify_entry search_entry delete_entry |
一個稱為 directory_controller.rb 的控制器腳本在 controllers 目錄內創建。此控制器腳本包含控制器動作 add_entry、modify_entry、search_entry 和 delete_entry。視圖模板 add_entry.rhtml、modify_entry.rhtml、earch_entry.rhtml 和 delete_entry.rhtml 在 views 文件夾內創建。
在接下來的小節內,修改控制器動作和視圖模板來添加一個目錄項、修改目錄項、搜索目錄項和刪除目錄項。
創建一個目錄項
下一步是在 Tivoli Directory Server 內創建一個目錄項。一個目錄項包含屬性和屬性值。目錄項的 DN 代表的是此目錄項的專有名稱。一個 DN 包含相對專有名和基礎 DN。在本例中,我們在 cn=localhost root/base DN 內創建一個目錄項。
如果還未啟動,請啟動 Tivoli Directory Server 實例。
每個目錄項由 dn 屬性標識。 objectClass 屬性指定數據類型以及每項內必須和可選的屬性。對象類形成了一個類的等級結構; 常用的對象類有 top、organization 和 organizationalPerson。所有對象類均是對象類 top 的子類。我們將用 top、person 和 organizationalPerson 對象類創建一個目錄服務:
修改 add_entry.rhtml 視圖模板來輸入此目錄項的數據。用 FormTagHelper 類的 form_tag 方法定義一個表單。用 text_field(object_name, method, options = {}) 方法定義此表單內的一個欄位。方法參數 object 代表的是此表單模板的一個對象。method 參數代表的是作為此表單對象的一個屬性的表單欄位。比如,如下的文本欄位:
text_field("directory_entry", "title", "size" => 20) |
轉變成 HTML 表單文本欄位:
<input type="text" id="directory_entry_title" name="directory_entry[title]" size="20" value="#{@directory_entry.title}" /> |
將姓、名、職務、電話號碼、部門和傳真號的文本欄位添加到 add_entry.rhtml。
文本欄位 | 屬性 |
---|---|
First name | gn |
Last name | sn |
Title | title |
Telephone number | telephoneNumber |
Department | physicalDeliveryOfficeName |
FAX number | facsimileTelephoneNumber |
清單 1 給出了 add_entry.rhtml。
<html> <body> <div> <table border='0' cellspacing='0' cellpadding='5'> <tr> <caption> Add Directory Entry </caption> </tr> <!-- start_form_tag --> <%= form_tag :action => "add_entry" %> <tr> <td>First Name*</td> <td><%= text_field(:add_entry, :gn) %></td> </tr><tr> <td>Last Name*</td> <td><%= text_field(:add_entry, :sn) %></td> </tr> <tr> <td>Title</td> <td><%= text_field(:add_entry, :title) %></td> </tr><tr> <td>Telephone Number</td> <td><%= text_field(:add_entry, :telephoneNumber) %></td> </tr> <tr> <td>Department</td> <td><%= text_field(:add_entry, :physicalDeliveryOfficeName) %></td> </tr> <tr> <td>Fax Number</td> <td><%= text_field(:add_entry, :facsimileTelephoneNumber) %></td> </tr> <tr> <td><input type="submit" value="Submit"></td> </tr> <%= end_form_tag %> </table> </div> * indicates a required field. </body> </html> |
修改控制器動作 add_entry 並檢索參數值。檢索名(:gn)和姓(:sn)並定義變數 cn。
values = params[:add_entry] gn=values[:gn] sn= values[:sn] cn=gn+sn |
定義此目錄項的專有名 dn,它由 rdn 和基礎 DN 組成。
dn="cn="+cn+",cn=localhost" |
檢索其他表單欄位的值。
title=values[:title] telephoneNumber=values[:telephoneNumber] physicalDeliveryOfficeName=values[:physicalDeliveryOfficeName] facsimileTelephoneNumber=values[:facsimileTelephoneNumber] |
定義一個變數 attr,它包含此目錄項的不同屬性。
attr = { :cn => cn, :objectclass => ['top', 'person', 'organizationalPerson'], :sn => sn, :title => title, :telephoneNumber => telephoneNumber, :physicalDeliveryOfficeName => physicalDeliveryOfficeName, :facsimileTelephoneNumber => facsimileTelephoneNumber } |
打開與 Tivoli Directory Server 的連接並使用 add() 方法將此目錄項添加到伺服器。
Net::LDAP.open( :host => 'localhost', :port => 389,:base => 'cn=localhost', :auth => { :method => :simple, :username => 'cn=root', |
用 add_entry.rhtml 模板創建一個目錄項。用如下命令啟動 WEBrick 伺服器:
C:/ruby/netldap>ruby script/server |
用 URL http://localhost:3000/directory/add_entry.rhtml 調用 add_entry.rhtml 視圖模板。為不同屬性指定值並單擊 Submit,如下所示。
在 Tivoli Directory Server 實例內的 cn=localhost 目錄項內創建了一個目錄項。在 Web Administration Tool 中選擇 cn=localhost 目錄項並單擊 Expand,如下所示。
用 Ruby on Rails 所添加的這個目錄在 cn=localhost 目錄項內的目錄項中列出。要列出此目錄項的屬性,選擇此目錄項並單擊 Edit attributes。
所添加的目錄項的屬性就會顯示出來。
修改一個目錄項
在本章節內,我們將修改一個目錄項。要修改的數據在 modify_entry.rhtml 內輸入。與添加目錄項類似,同樣要用 FormTagHelper 類的 form_tag 方法向 modify_entry.rhtml 視圖模板添加一個表單。用 FormHelper 類的 text_field 方法添加表單欄位。清單 2 給出了這個 modify_entry.rhtml 視圖模板。
<html> <body> <div> <table border='0' cellspacing='0' cellpadding='5'> <tr> <caption> Modify Directory Entry </caption> </tr> <!-- start_form_tag --> <%= form_tag :action => "modify_entry" %> <tr> <td>First Name*</td> <td><%= text_field(:modify_entry, :gn) %></td> </tr><tr> <td>Last Name*</td> <td><%= text_field(:modify_entry, :sn) %></td> </tr> <tr> <td>Title</td> <td><%= text_field(:modify_entry, :title) %></td> </tr><tr> <td>Telephone Number</td> <td><%= text_field(:modify_entry, :telephoneNumber) %></td> </tr> <tr> <td>Department</td> <td><%= text_field(:modify_entry, :physicalDeliveryOfficeName) %></td> </tr> <tr> <td>Fax Number</td> <td><%= text_field(:modify_entry, :facsimileTelephoneNumber) %></td> </tr> <tr> <td><input type="submit" value="Submit"></td> </tr> <%= end_form_tag %> </table> </div> * indicates a required field. </body> </html> |
在 modify_entry.rhtml 模板被提交時,會調用控制器 directory 的 modify_entry 控制器動作。修改 modify_entry 控制器動作。
檢索表單欄位 :gn 和 :sn 的值,並定義一個變數 cn。
values = params[:modify_entry] gn=values[:gn] sn= values[:sn] cn=gn+sn |
目錄項由一個專有名標識。定義要修改的這個目錄項的 DN。
dn="cn="+cn+",cn=localhost" |
檢索其他表單欄位的值。
title=values[:title] telephoneNumber=values[:telephoneNumber] physicalDeliveryOfficeName=values[:physicalDeliveryOfficeName] facsimileTelephoneNumber=values[:facsimileTelephoneNumber] |
打開與 Tivoli Directory Server 的連接並用 replace_attribute 方法替換這些屬性值。比如,:title 屬性被替換如下:
Net::LDAP.open( :host => 'localhost', :port => 389,:base => 'cn=localhost', :auth => { :method => :simple, :username => 'cn=root', |
目錄項在 modify_entry.rhtml 視圖模板中被修改。啟動 WEBrick Web 伺服器並使用 URL http://localhost:3000/directory/modify_entry.rhtml 調用 modify_entry.rhtml 視圖模板。指定要修改的目錄項以及被修改的屬性。單擊 Submit,如下所示。
此目錄項得到了修改,如 Web Administration Tool 所示。
搜索一個目錄
本節展示了如何搜索一個目錄項。目錄搜索的結果顯示在使用 Ajax Web 技術輸入目錄項數據的同一個頁面中。此 Ajax Web 技術由原型庫實現。這個原型庫包括類 PrototypeHelper 來創建一個表單,這個表單可使用 Ajax 進行非同步更新。將這個原型庫包含在 search_entry.rhtml 視圖模板內。
<%= javascript_include_tag "prototype" %> |
用 PrototypeHelper 類的 form_remote_tag 方法添加一個使用 Ajax 提交的表單。form_remote_tag 的 :update 選項指定了由伺服器響應進行更新的那個表單元素。:url 選項指定了此表單被提交到的那個 URL,而控制器動作則由 :action 參數指定。
<%=form_remote_tag(:update=>"directory_entry", :url=>{:action=>:search_entry}) %> <% end_form_tag %> |
用 FormTagHelper 類的 text_field_tag 指定此目錄項的輸入欄位。而要更新的表單元素則作為 div 指定。
<div id="directory_entry"></div> |
search_entry.rhtml 視圖模板如清單 3 所示。
<html><head> <title></title> <%= javascript_include_tag "prototype" %> </head> <body> <caption> Search Directory Entry </caption> <%=form_remote_tag(:update=>"directory_entry", :url=>{:action=>:search_entry}) %> <table> <tr> <label>First Name*</label> <%=text_field_tag:firstName %></tr> <tr><label>Last Name</label> <%=text_field_tag:lastName %></tr> <%=submit_tag "Search" %> </table> <caption> <b> Directory Entry Table</b> </caption> <div id="directory_entry"></div> <% end_form_tag %> * indicates a required field. </body> </html> |
在 search_entry.rhtml 表單被提交時,會調用此目錄控制器的 search_entry 控制器動作。修改 search_entry 動作。檢索 :gn 和 :sn 欄位的值,並定義要搜索的目錄項的基礎 DN。
gn=values[:gn] sn= values[:sn] cn=gn+sn treebase= "cn="+cn+",cn=localhost" |
指定要檢索的目錄項的屬性。
attrs = ["cn", "sn","title", "telephoneNumber","physicalDeliveryOfficeName", "facsimileTelephoneNumber"] |
打開與 Tivoli Directory Server 的連接並使用 Net::LDAP 類的 search 方法搜索這個特定的目錄項。
Net::LDAP.open( :host => 'localhost', :port => 389,:base => 'cn=localhost', :auth => { :method => :simple, :username => 'cn=root', |
search 方法返回一個結果集。迭代此結果集並創建一個 HTML 表來作為響應發送給 search_entry.rhtml 視圖模板。比如,針對 cn 屬性的一行就被添加到了此表中。
directoryEntry+="<tr>" directoryEntry+="<td>cn</td>" directoryEntry+="<td>"+"#{directory.cn}"+"</td>" directoryEntry+="</tr>" |
用 URL http://localhost:3000/directory/search_entry.rhtml 調用 asearch_entry.rhtml 視圖模板來搜索此目錄項。指定 :gn 和 :sn 屬性的值以形成目錄項的 rdn,並單擊 Search。
此目錄項屬性即被列出。
刪除一個目錄項
在本節中,我們將刪除一個目錄項。目錄項由 DN 標識,而 DN 由 rdn 和基礎 DN 組成。要被修改的目錄項的 RDN 在 delete_entry.rhtml 視圖模板內指定。form_tag 方法被用來創建一個表單,text_field 標記被用來創建一個表單文本欄位。 delete_entry.rhtml 視圖模板包含名和姓的輸入欄位,如下所示。
<html> <body> <div> <table border='0' cellspacing='0' cellpadding='5'> <tr> <caption> Delete Entry </caption> </tr> <!-- start_form_tag --> <%= form_tag :action => "delete_entry" %> <tr> <td>First Name*</td> <td><%= text_field(:delete_entry, :gn) %></td> </tr><tr> <td>Last Name*</td> <td><%= text_field(:delete_entry, :sn) %></td> </tr><tr> <td><input type="submit" value="Submit"></td> </tr> <%= end_form_tag %> </table> </div> * indicates a required field. </body> </html> |
當 delete_entry.rhtml 表單被提交時,會調用 directory 控制器的 delete_entry 控制器動作。delete_entry 控制器動作檢索這些表單欄位的值並創建要刪除的那個目錄項的 DN。
values = params[:delete_entry] gn=values[:gn] sn= values[:sn] cn=gn+sn dn="cn="+cn+",cn=localhost" |
打開與目錄伺服器的連接並用 Net::LDAP 類的 delete 方法刪除此目錄項。
Net::LDAP.open( :host => 'localhost', :port => 389, :base => 'cn=localhost', :auth => { :method => :simple, :username => 'cn=root', :password => 'tivoli' } ) do |ldap| ldap.delete :dn => dn end |
要刪除一個目錄項,用 URL http://localhost:3000/directory/delete_entry.rhtml 調用 delete_entry.rhtml 視圖模板。指定要刪除的那個目錄項的 :gn(名)和 :sn(姓)屬性並單擊 Submit。
此目錄項即被刪除,如 Web Administration Tool 內所示。
directory_controller.rb 控制器腳本如下所示。
require 'net/ldap' class DirectoryController < ApplicationController def add_entry values = params[:add_entry] gn=values[:gn] sn= values[:sn] cn=gn+sn dn="cn="+cn+",cn=localhost" title=values[:title] telephoneNumber=values[:telephoneNumber] physicalDeliveryOfficeName=values[:physicalDeliveryOfficeName] facsimileTelephoneNumber=values[:facsimileTelephoneNumber] attr = { :cn => cn, :objectclass => ['top', 'person', 'organizationalPerson'], :sn => sn, :title => title, :telephoneNumber => telephoneNumber, :physicalDeliveryOfficeName => physicalDeliveryOfficeName, :facsimileTelephoneNumber => facsimileTelephoneNumber } Net::LDAP.open( :host => 'localhost', :port => 389,:base => 'cn=localhost', :auth => { :method => :simple, :username => 'cn=root', |
結束語
在本文中,您安裝了 Ruby on Rails 和 Net::LDAP Ruby gem。了解了如何在 Tivoli Directory Server V6.0 內創建一個目錄項,然後修改此目錄項,搜索此目錄項和刪除此目錄項,這些均使用 Ruby 腳本語言實現。
就開發 LDAP 目錄服務方面的應用而言,Ruby 完全可以與 PHP 這種最為常用的腳本語言媲美。根據 TIOBE Programming Community Index 的統計,過去一年來,Ruby 的使用已經有所增加。(責任編輯:A6)
[火星人 ] 使用 Ruby on Rails 在 Tivoli Directory Server V6.0 內創建 LD已經有797次圍觀