Ruby 简明教程

Ruby - LDAP Tutorial

Ruby/LDAP 是 Ruby 的一个扩展库。它提供了一些 LDAP 库的接口,如 OpenLDAP、UMich LDAP、Netscape SDK、ActiveDirectory。

Ruby/LDAP is an extension library for Ruby. It provides the interface to some LDAP libraries like OpenLDAP, UMich LDAP, Netscape SDK, ActiveDirectory.

应用程序开发的通用 API 在 RFC1823 中描述,并由 Ruby/LDAP 支持。

The common API for application development is described in RFC1823 and is supported by Ruby/LDAP.

Ruby/LDAP Installation

您可以从 SOURCEFORGE.NET 下载并安装完整的 Ruby/LDAP 程序包。

You can download and install a complete Ruby/LDAP package from SOURCEFORGE.NET.

在安装 Ruby/LDAP 之前,请确保您具有以下组件:

Before installing Ruby/LDAP, make sure you have the following components −

  1. Ruby 1.8.x (at least 1.8.2 if you want to use ldap/control).

  2. OpenLDAP, Netscape SDK, Windows 2003 or Windows XP.

现在,您可以使用标准 Ruby 安装方法。在开始之前,如果您想查看 extconf.rb 的可用选项,请使用“--help”选项运行它。

Now, you can use standard Ruby Installation method. Before starting, if you’d like to see the available options for extconf.rb, run it with '--help' option.

$ ruby extconf.rb [--with-openldap1|--with-openldap2| \
                   --with-netscape|--with-wldap32]
$ make
$ make install

NOTE − 如果您在 Windows 上构建软件,您可能需要使用 nmake 而不是 make。

NOTE − If you’re building the software on Windows, you may need to use nmake instead of make.

Establish LDAP Connection

这是一个两步过程:

This is a two-step process −

Step 1 − Create Connection Object

以下是创建与 LDAP 目录连接的语法。

Following is the syntax to create a connection to a LDAP directory.

LDAP::Conn.new(host = 'localhost', port = LDAP_PORT)
  1. host − This is the host ID running LDAP directory. We will take it as localhost.

  2. port − This is the port being used for LDAP service. Standard LDAP ports are 636 and 389. Make sure which port is being used at your server otherwise you can use LDAP::LDAP_PORT.

此调用将返回与服务器、主机在端口 port 上的新 LDAP::Conn 连接。

This call returns a new LDAP::Conn connection to the server, host, on port port.

Step 2 − Binding

这里是我们通常指定将在会话剩余部分中使用的用户名和密码。

This is where we usually specify the username and password we will use for the rest of the session.

以下是绑定一个 LDAP 连接的语法,使用 DN, dn ,凭据, pwd ,和绑定方法, method

Following is the syntax to bind an LDAP connection, using the DN, dn, the credential, pwd, and the bind method, method

conn.bind(dn = nil, password = nil, method = LDAP::LDAP_AUTH_SIMPLE)do
....
end

您可以使用相同的方法而没有代码块。在这种情况下,您需要如下显式解绑连接 −

You can use the same method without a code block. In this case, you would need to unbind the connection explicitly as follows −

conn.bind(dn = nil, password = nil, method = LDAP::LDAP_AUTH_SIMPLE)
....
conn.unbind

如果提供了代码块,则 self 被传递给该块。

If a code block is given, self is yielded to the block.

我们现在可以在 bind 方法的块(bind 和 unbind 之间)中执行搜索、添加、修改或删除操作,前提是我们有适当的权限。

We can now perform search, add, modify or delete operations inside the block of the bind method (between bind and unbind), provided we have the proper permissions.

Example

假设我们正在本地服务器上工作,让我们将适当的主机、域、用户 ID 和密码等组合在一起。

Assuming we are working on a local server, let’s put things together with appropriate host, domain, user id and password, etc.

#/usr/bin/ruby -w

require 'ldap'

$HOST =    'localhost'
$PORT =    LDAP::LDAP_PORT
$SSLPORT = LDAP::LDAPS_PORT

conn = LDAP::Conn.new($HOST, $PORT)
conn.bind('cn = root, dc = localhost, dc = localdomain','secret')
....
conn.unbind

Adding an LDAP Entry

添加 LDPA 条目是一个两步过程 −

Adding an LDPA entry is a two step process −

Step 1 − Creating LDAP::Mod object

我们需要将 LDAP::Mod 对象传递给 conn.add 方法以创建条目。以下是创建 LDAP::Mod 对象的简单语法 −

We need LDAP::Mod object pass to conn.add method to create an entry. Here is a simple syntax to create LDAP::Mod object −

Mod.new(mod_type, attr, vals)
  1. mod_type − One or more option LDAP_MOD_ADD, LDAP_MOD_REPLACE or LDAP_MOD_DELETE.

  2. attr − should be the name of the attribute on which to operate.

  3. vals − is an array of values pertaining to attr. If vals contains binary data, mod_type should be logically OR’ed (|) with LDAP_MOD_BVALUES.

此调用返回 LDAP::Mod 对象,可以将其传递给 LDAP::Conn 类中的方法,例如 Conn#add、Conn#add_ext、Conn#modify 和 Conn#modify_ext。

This call returns LDAP::Mod object, which can be passed to methods in the LDAP::Conn class, such as Conn#add, Conn#add_ext, Conn#modify and Conn#modify_ext.

Step 2 − Calling conn.add Method

一旦我们准备好 LDAP::Mod 对象,就可以调用 conn.add 方法来创建条目。下面是调用此方法的语法 −

Once we are ready with LDAP::Mod object, we can call conn.add method to create an entry. Here is a syntax to call this method −

conn.add(dn, attrs)

此方法添加了一个条目,带有 DN、dn 和属性 attrs。此处,attrs 应是 LDAP::Mod 对象的数组或属性/值数组对的哈希。

This method adds an entry with the DN, dn, and the attributes, attrs. Here, attrs should be either an array of LDAP::Mod objects or a hash of attribute/value array pairs.

Example

下面是一个完整示例,它将创建两个目录条目 −

Here is a complete example, which will create two directory entries −

#/usr/bin/ruby -w

require 'ldap'

$HOST =    'localhost'
$PORT =    LDAP::LDAP_PORT
$SSLPORT = LDAP::LDAPS_PORT

conn = LDAP::Conn.new($HOST, $PORT)
conn.bind('cn = root, dc = localhost, dc = localdomain','secret')

conn.perror("bind")
entry1 = [
   LDAP.mod(LDAP::LDAP_MOD_ADD,'objectclass',['top','domain']),
   LDAP.mod(LDAP::LDAP_MOD_ADD,'o',['TTSKY.NET']),
   LDAP.mod(LDAP::LDAP_MOD_ADD,'dc',['localhost']),
]

entry2 = [
   LDAP.mod(LDAP::LDAP_MOD_ADD,'objectclass',['top','person']),
   LDAP.mod(LDAP::LDAP_MOD_ADD, 'cn', ['Zara Ali']),
   LDAP.mod(LDAP::LDAP_MOD_ADD | LDAP::LDAP_MOD_BVALUES, 'sn',
                     ['ttate','ALI', "zero\000zero"]),
]

begin
   conn.add("dc = localhost, dc = localdomain", entry1)
   conn.add("cn = Zara Ali, dc = localhost, dc =  localdomain", entry2)
rescue LDAP::ResultError
   conn.perror("add")
   exit
end
conn.perror("add")
conn.unbind

Modifying an LDAP Entry

修改条目类似于添加条目。只需使用属性调用 modify 方法来修改,而不是用 add。下面是 modify 方法的简单语法。

Modifying an entry is similar to adding one. Just call the modify method instead of add with the attributes to modify. Here is a simple syntax of modify method.

conn.modify(dn, mods)

此方法使用 DN、dn 和属性 mods 修改条目。此处,mods 应是 LDAP::Mod 对象的数组或属性/值数组对的哈希。

This method modifies an entry with the DN, dn, and the attributes, mods. Here, mods should be either an array of LDAP::Mod objects or a hash of attribute/value array pairs.

Example

为了修改上一节中添加的条目的姓氏,我们可以编写 −

To modify the surname of the entry, which we added in the previous section, we would write −

#/usr/bin/ruby -w

require 'ldap'

$HOST =    'localhost'
$PORT =    LDAP::LDAP_PORT
$SSLPORT = LDAP::LDAPS_PORT

conn = LDAP::Conn.new($HOST, $PORT)
conn.bind('cn = root, dc = localhost, dc = localdomain','secret')

conn.perror("bind")
entry1 = [
   LDAP.mod(LDAP::LDAP_MOD_REPLACE, 'sn', ['Mohtashim']),
]

begin
   conn.modify("cn = Zara Ali, dc = localhost, dc = localdomain", entry1)
rescue LDAP::ResultError
   conn.perror("modify")
   exit
end
conn.perror("modify")
conn.unbind

Deleting an LDAP Entry

要删除条目,请使用 distinguished name 作为参数来调用 delete 方法。下面是 delete 方法的简单语法。

To delete an entry, call the delete method with the distinguished name as parameter. Here is a simple syntax of delete method.

conn.delete(dn)

此方法使用 DN、dn 删除条目。

This method deletes an entry with the DN, dn.

Example

要删除上一节中添加的 Zara Mohtashim 条目,我们可以编写 −

To delete Zara Mohtashim entry, which we added in the previous section, we would write −

#/usr/bin/ruby -w

require 'ldap'

$HOST =    'localhost'
$PORT =    LDAP::LDAP_PORT
$SSLPORT = LDAP::LDAPS_PORT

conn = LDAP::Conn.new($HOST, $PORT)
conn.bind('cn = root, dc = localhost, dc = localdomain','secret')

conn.perror("bind")
begin
   conn.delete("cn = Zara-Mohtashim, dc = localhost, dc = localdomain")
rescue LDAP::ResultError
   conn.perror("delete")
   exit
end
conn.perror("delete")
conn.unbind

Modifying the Distinguished Name

无法使用 modify 方法修改条目的 distinguished name。可以使用 modrdn 方法来代替。以下是 modrdn 方法的简单语法 −

It’s not possible to modify the distinguished name of an entry with the modify method. Instead, use the modrdn method. Here is simple syntax of modrdn method −

conn.modrdn(dn, new_rdn, delete_old_rdn)

此方法使用 DN、dn 修改条目的 RDN,为其提供新的 RDN、new_rdn。如果 delete_old_rdn 为 true,则旧的 RDN 值将从条目中删除。

This method modifies the RDN of the entry with DN, dn, giving it the new RDN, new_rdn. If delete_old_rdn is true, the old RDN value will be deleted from the entry.

Example

假设我们有以下条目 −

Suppose we have the following entry −

dn: cn = Zara Ali,dc = localhost,dc = localdomain
cn: Zara Ali
sn: Ali
objectclass: person

然后,我们可以使用以下代码修改它的 distinguished name −

Then, we can modify its distinguished name with the following code −

#/usr/bin/ruby -w

require 'ldap'

$HOST =    'localhost'
$PORT =    LDAP::LDAP_PORT
$SSLPORT = LDAP::LDAPS_PORT

conn = LDAP::Conn.new($HOST, $PORT)
conn.bind('cn = root, dc = localhost, dc = localdomain','secret')

conn.perror("bind")
begin
   conn.modrdn("cn = Zara Ali, dc = localhost, dc = localdomain", "cn = Zara Mohtashim", true)
rescue LDAP::ResultError
   conn.perror("modrdn")
   exit
end
conn.perror("modrdn")
conn.unbind

要在 LDAP 目录中执行搜索,请使用包含三种不同搜索模式之一的 search 方法 −

To perform a search on a LDAP directory, use the search method with one of the three different search modes −

  1. LDAP_SCOPE_BASEM − Search only the base node.

  2. LDAP_SCOPE_ONELEVEL − Search all children of the base node.

  3. LDAP_SCOPE_SUBTREE − Search the whole subtree including the base node.

Example

在这里,我们将搜索 cn = localhost,cn = localdomain 项的整个子树以查找人员对象 -

Here, we are going to search the whole subtree of entry dc = localhost, dc = localdomain for person objects −

#/usr/bin/ruby -w

require 'ldap'

$HOST =    'localhost'
$PORT =    LDAP::LDAP_PORT
$SSLPORT = LDAP::LDAPS_PORT

base = 'dc = localhost,dc = localdomain'
scope = LDAP::LDAP_SCOPE_SUBTREE
filter = '(objectclass = person)'
attrs = ['sn', 'cn']

conn = LDAP::Conn.new($HOST, $PORT)
conn.bind('cn = root, dc = localhost, dc = localdomain','secret')

conn.perror("bind")
begin
   conn.search(base, scope, filter, attrs) { |entry|
      # print distinguished name
      p entry.dn
      # print all attribute names
      p entry.attrs
      # print values of attribute 'sn'
      p entry.vals('sn')
      # print entry as Hash
      p entry.to_hash
   }
rescue LDAP::ResultError
   conn.perror("search")
   exit
end
conn.perror("search")
conn.unbind

这会对每个匹配项调用提供的代码块,其中 LDAP 项由 LDAP::Entry 类的实例表示。使用 search 的最后一个参数,您可以指定感兴趣的属性,省略所有其他属性。如果您在这里传递 nil,则会返回所有属性,与关系数据库中的“SELECT *”相同。

This invokes the given code block for each matching entry where the LDAP entry is represented by an instance of the LDAP::Entry class. With the last parameter of search, you can specify the attributes in which you are interested, omitting all others. If you pass nil here, all attributes are returned same as "SELECT *" in relational databases.

LDAP::Entry 类的 dn 方法(get_dn 的别名)返回项的专有名称,使用 to_hash 方法,您可以获得其属性的哈希表示形式(包括专有名称)。若要获取项属性的列表,请使用 attrs 方法(get_attributes 的别名)。此外,要获取一个特定属性值的列表,请使用 vals 方法(get_values 的别名)。

The dn method (alias for get_dn) of the LDAP::Entry class returns the distinguished name of the entry, and with the to_hash method, you can get a hash representation of its attributes (including the distinguished name). To get a list of an entry’s attributes, use the attrs method (alias for get_attributes). Also, to get the list of one specific attribute’s values, use the vals method (alias for get_values).

Handling Errors

Ruby/LDAP 定义了两种不同的异常类 -

Ruby/LDAP defines two different exception classes −

  1. In case of an error, the new, bind or unbind methods raise an LDAP::Error exception.

  2. In case of add, modify, delete or searching an LDAP directory raise an LDAP::ResultError.

Further Reading

有关 LDAP 方法的完整详细信息,请参阅 LDAP Documentation 的标准文档。

For complete details on LDAP methods, please refer to the standard documentation for LDAP Documentation.