.NET Client Classes for openldap/winldap






4.88/5 (15投票s)
一个使用 LDAP/OpenLDAP 的 .Net 示例
LDAP - 轻量级目录访问协议
环境
客户端 | 服务器 |
openldap (明文|tls) | openldap |
winldap (明文|tls) | openldap |
openldap (明文|tls) | Active Directory |
winldap (明文|tls) | Active Directory |
注意: 在使用该库之前,您需要仔细检查代码。
构建 openldap 客户端库
以下是在 Windows 上构建 openldap 的步骤。要构建客户端库,不需要太多调整。我使用的是 openldap-2.1.12
。 .dsp 和 .dsw 文件位于 ..\build\
目录下。如果打开 main.dsw,它包含了 openldap 服务器以及 ldap 客户端库。对于客户端,您需要构建 libldap_r
和 liblber
项目。我没有使用 SASL 身份验证机制,因此我从 ldap 库中删除了 SASL 和 Regex 的依赖项(尽管,添加 sasl/regex 支持并不难)。要删除 SASL/Regex 依赖项,请展开 setup 项目。打开 portable.nt
文件并注释掉
//#define HAVE_REGEX_H 1 //#define HAVE_CYRUS_SASL 1
(或者参考 此处的说明 。)
右键单击 libldap_r
(线程安全版本) 和 liblber
项目,然后重新生成。这应该可以成功构建。现在,您需要为 VS.NET 设置库搜索目录,指向输出的 oldap_r.lib
和 olber32.lib
的位置。对于头文件也一样。
..\openldap-2.1.12\Debug
或 ..\openldap-2.1.12\Release
或某个通用目录,或者重命名 debug 和 release 文件。..\openldap-2.1.12\include
为测试目的在 Windows 上构建 openldap 服务器
请参考 此处的构建说明,这适用于 openldap-2.0.xx 版本。
您也可以成功构建 openldap-2.1.xx,我使用的是 Sleepycat Berkley 的 db-4.1.xx 和 cyrus-sasl-1.5.xx。一切构建完成后,您需要将 *.exe 和 *.dll 文件复制到某个目录,该目录将作为 openldap 服务器的基础目录。
您需要将 schema 目录从 ..\openldap\openldap-2.1.12\servers\slapd\schema
复制到您的 openldap 基础目录,并将示例 slapd.conf 文件从 ..\openldap\openldap-2.1.12\servers\slapd\slapd.conf
复制过来。
在 slapd.conf 中,在任何 include 语句之前添加 ucdata-path。如下所示:
ucdata-path "X:/openldap-2.1.12/ucgendat".
然后打开命令提示符并运行:
ucgendat.exe -o X:/openldap-2.1.12/ucgendat
如果出现此错误: error loading ucdata (error -127),您就知道 ucgendata 没有正确设置。在 2.0.xx 版本中,这并不是必需的。
根据您的需求填写/修改 slapd.conf 的其余部分。请查阅各种资源,特别是 slapd.conf 的 man 页,位于 http://www.openldap.org/software/man.cgi,然后输入 slapd.conf,还可以查看 快速入门指南 和 管理员指南。
为了调试可能的错误,您可以运行 slapd -d 255
。要做到这一点,您需要使用 LDAP_DEBUG
进行编译。这可以在 portable.nt 文件中添加,它位于 setup 项目下;在顶部附近添加:
#define LDAP_DEBUG 1
如果您想添加 ssl/tls 支持,可以通过 openssl 实现。您需要获取最新的 openssl 版本(例如 openssl-0.9.7a),并按照随包提供的 INSTALL.W32 文件中的说明进行操作。构建 openssl 为 dll 或静态库后,您需要将其 .lib/.h 目录添加到 VS.NET 的库/头文件搜索目录中。现在,您需要从 openldap 解决方案的 setup 项目中打开 portable.nt。在顶部附近添加此内容:
#define HAVE_TLS 1 #define HAVE_OPENSSL_SSL_H 1 #pragma comment(lib, "ssleay32r.lib") #pragma comment(lib, "libeay32r.lib")
然后构建 openldap。现在您需要编辑 slapd.conf 文件。相关的选项有:TLSVerifyClient
, TLSCertificateFile
, TLSCertificateKeyFile
, TLSCACertificateFile
, TLSCipherSuite
等。
现在您可以启动 ldap 来监听 ssl/tls 连接了。
slapd -h "ldaps://somehost ldap://somehost
虽然使用 ldap_start_tls_s
时不需要 ldaps://,因为它在普通的 ldap 端口 (389) 上通信,而不是在 ssl 的 636 端口上。当使用 winldap 客户端连接时,服务器证书的 CA 必须被客户端 PC 信任,这意味着它必须安装在受信任的 CA 下。您可以通过使用 Internet Explorer 连接到服务器来检查服务器证书是否存在任何问题。有关 winldap 的更多故障排除信息,请在 groups.google.com 中搜索:ldap_sslinit
故障排除组:microsoft.public.platformsdk.active.directory,您可以在那里找到 mskb 文章。
Ldap .NET 类用法
Connection
LdapClient c = new LdapClient("127.0.0.1",
LdapClient.DefaultPort,true /*version 3?*/, true /*use tls?*/);
c.ldap_simple_bind_s("bind_dn", "your_pass");
搜索
LdapResult res;
int count = c.ldap_search_ext_s("dn_to_start_the_search_at",
LDAPSearchScope.LDAPSCOPE_SUBTREE,
"sn=*", /* search filter */
new string[0], /* attribs to return, empty for all */
false, /* return attrsonly? */
60, /* allow 60 secs for the search */
0, /* 0 == no size limit on returned entries */
out res);
Console.WriteLine("Search Returned: {0}", count);
foreach(Oldap.LdapEntry entry in res)
{
Console.WriteLine("dn:{0}", entry.DN);
foreach(Oldap.LdapAttribute attr in entry)
{
if(attr.Name == "string_type?")
foreach(string val in attr.StringValues)
Console.WriteLine("{0}: {1}", attr.Name, val);
else if(attr.Name == "binary_type?")
foreach(Byte[] val in attr.BinaryValues)
{
mem = new MemoryStream();
mem.Write(val, 0, val.Length);
//do something with it
}
}
Console.WriteLine();
}
添加新条目
(支持的类型:String 或 String[],Byte[] 或 Byte[] 数组)
string entryDN = "dn_of_new_entry";
ListDictionary attrval = new ListDictionary();
attrval["objectClass"]=new string[]{"top", "person"};
//person class is abstract in AD
attrval["cn"]=new string[]{"test"};
attrval["sn"]="test";
//Byte[] example. To add multiple binary values you have
//to pass array of byte[], so something like
//ArrayList that has Added byte[]s and then gives the array
//with ToArray method should work
//Bitmap bmp = new Bitmap("..\\..\\some.bmp");
//mem = new MemoryStream();
//bmp.Save(mem, ImageFormat.Bmp);
//attrval["personPhoto"]= new object[]{mem.ToArray()}; //aray of byte[]
//or
//attrval["personPhoto"]= mem.ToArray(); //byte[]
//personPhoto is custom attribute with
//SYNTAX 1.3.6.1.4.1.1466.115.121.1.40
//in AD it's 2.5.5.10
//To support it i defined a new objectClass
//that includes it, and "person" objectClass
//used in above example doesn't know about it.
c.ldap_add_s(entryDN, attrval);
if(c.ldap_compare_s(entryDN, "cn", "test") == true)
//check if value exists for attrib under specific entry
替换现有条目中的属性
attrval["sn"]="test_modified";
c.ldap_mod_replace(entryDN, attrval);
向现有条目添加属性
attrval["telephoneNumber"]=new string[]{"phone1","phone2"};
c.ldap_mod_add(entryDN, attrval);
删除现有条目中的属性
attrval["telephoneNumber"]=new string[0];
//remove attribute completely
attrval["telephoneNumber"]=new string[]{"phone2"};
//remove specific value from attribute
//or whole attribute if it's the only value
c.ldap_mod_delete(entryDN, attrval);
删除整个条目
c.ldap_delete_s(entryDN);
抛出异常
LDAPException
LDAPExceptionPartialResult - thrown when searching and specifying size limit.
partial_count data member has the returned count.
InvalidCastException
其余的 ldap 函数,包括异步方法、引用(LDAP_OPT_REFERRALS)等……将根据需要添加。
参考
- LDAP Implementation Cookbook (IBM Red Book) (ibm.com)
- A Recipe for Configuring and Operating LDAP Directories (georgetown.edu)
- Lightweight Directory Access Protocol (v3) - rfc2251(faqs.org)
- LDAP (v3) - Attribute Syntax Definitions - rfc2252 (faqs.org)
- String Representation of LDAP Search Filters - rfc2254 (faqs.org)
- LDAP (v3): UTF-8 String Representation of Distinguished Names - rfc2253 (faqs.org)
- Technical Overview of Directory Services Using the X.500 Protocol - rfc1309 (faqs.org)
- COSINE and Internet X.500 Schema - rfc1274 (faqs.org)
- The LDAP URL Format - rfc2255 (faqs.org)
- The LDAP Data Interchange Format (LDIF) - Technical Specification (faqs.org)
- OpenLDAP 2.1 Administrator's Guide (openldap.org)
- OpenLDAP 2.0 Schema Extension to support MS/Outlook, Netscape 4.5+ (yolinux.com)
- Common LDAP RFCs (mskb)
- Introduction to Lightweight Directory Access Protocol (LDAP) (mskb)
- OutLook2000: (CW) How to Install and Use the LDAP Service (mskb)
- HOWTO: Use ADO to Access Objects Through an ADSI LDAP Provider (mskb)
- Obtaining an Object Identifier - OID (msdn)
Winldap 相关
- Lightweight Directory Access Protocol (msdn)
- Understanding LDAP (microsoft.com)
- Error Message: 0x80090322 When Binding with SSL to Site Server LDAP (mskb)
Winldap 常见的 SSL 错误
0x80090322 - "目标主体名称不正确"
0x80090325 - "证书链由不受信任的颁发机构颁发"
- HOW TO: Enable Schannel Logging (mskb)
- Microsoft LDAP Error Codes (mskb)
Active Directory 相关
- Microsoft Visual Studio.NET Server Explorer Extensions for Active Directory (msdn)
- Using LDIFDE to Import and Export Directory Objects to Active Directory (mskb)
- How to Modify Schema Information Using the Ldifde Utility(mskb)
- Toolbox for LDAP Directory Developers (mskb .doc)
- Active Directory Architecture (msdn)
- Active Directory Schema (msdn)
- Syntaxes for Active Directory Attributes (msdn)
- Characteristics of Object Classes (msdn)
- LDIF Scripts (msdn)
- Extending the AD Schema (msdn)
- An ADSI Primer (winscriptingsolutions.com)
- Active Directory Glossary (microsoft.com)
- Using Good Programming Practices with LDAP (msdn)
- How to Use Csvde.exe to Import Contacts into Active Directory (mskb)
- HOW TO: Use Csvde to Import Contacts and User Objects into Active Directory (mskb)