C#通过LDAP访问目录服务
C#通过LDAP访问目录服务
本文介绍如何编写C#程序通过LDAP协议访问微软目录服务获得用户在目录中的属性信息。在开始部分先简单句介绍LDAP协议,然后是技术比较及实现部分。
目录
- 什么是LDAP?
- 简介
- 概述
- 协议内容
- 产品
- 查询用户信息
- 用途
什么是LDAP?
简介
LDAP是轻型目录访问协议(Lightweight Directory Access Protocol,/ˈɛldæp/),是一个开放的、中立的、工业标准的应用协议,通过IP协议提供访问控制和维护分布式信息的目录信息访问服务。
目录服务在开发内部网路和与互联网应用共享用户(用户组织)、系统、网络、服务和应用的过程中占据了重要地位。例如,目录服务提供了组织有序的记录集合,通常有层级结构,例如公司电子邮件目录。同理,也提供包含了地址和电话号码的电话簿。
LDAP由互联网工程任务组(IETF)的文档RFC定义,使用了描述语言ASN.1定义。最新的版本是版本3,由RFC 4511所定义。例如,一个用语言描述的LDAP的搜索如:“在公司邮件目录中搜索公司位于那什维尔名字中含有“Jessy”的有邮件地址的所有人。请返回他们的全名,电子邮件,头衔和简述。”
LDAP的一个常用用途是单点登录,用户可以在多个服务中使用同一个密码,通常用于公司内部网站的登录中(这样他们可以在公司计算机上登录一次,便可以自动在公司内部网上登录)。
LDAP基于X.500标准的子集。因为这个关系,LDAP有时被称为X.500-lite。
概述
鉴于原先的目录访问协议(Directory Access Protocol即DAP)对于简单的互联网客户端使用太复杂,IETF设计并指定LDAP做为使用X.500目录的更好的途径。LDAP在TCP/IP之上定义了一个相对简单的升级和搜索目录的协议。
常用词"LDAP目录"可能会被误解,而实际并没有"LDAP目录"这么一个目录种类。通常可以用它来描述任何使用LDAP协议访问并能用X.500标识符标识目录中对象的目录。
协议内容
LDAP目录与普通数据库结构的主要不同之处在于数据的组织方式,它是一种有层次的、树形结构。所有条目的属性的定义是对象类(object class)的组成部分,并组成在一起构成结构(schema);那些在组织内代表个人的结构被命名为白页结构(white pages schema)。数据库内的每个条目都与若干对象类联系,而这些对象类决定了一个属性是否为可选和它保存哪些类型的信息。属性的名字一般是一个易于记忆的字符串,例如用cn为通用名(common name)命名,而"mail"代表e-mail地址。属性取值依赖于其类型,并且LDAPv3中一般非二进制值都遵从UTF-8字符串语法。例如,mail属性包含值“user@example.com”;jpegPhotos属性一般包含JPEG/JFIF格式的图片。
LDAP目录条目可描述一个层次结构,这个结构可以反映一个政治、地理或者组织的范畴。在原始的X.500模型中,反应国家的条目位于树的顶端;接着是州或者民族组织。典型的LDAP配置使用DNS名称作为树形结构的顶端,下列是代表人、文档、组织单元、打印机和其他任何事务的条目。
LDAP影响了后续的Internet协议,包括新版本的X.500、Directory Services Markup Language (DSML)、Service Provisioning Markup Language (SPML)和Service Location Protocol.
产品
LDAP从下面厂商获得广泛支持:
- Apache - Apache Directory Server
- Apple(苹果) - Open Directory
- AT&T
- Banyan
- HP(惠普)
- IBM - IBM Lotus
- ISODE - M-Vault Server
- Microsoft(微软) - Active Directory
- Netscape(网景) - Sun Microsystems和Red Hat的产品
- Novell - eDirectory
- OctetString - VDE Server
- Oracle(甲骨文) - Oracle Internet Directory
- Red Hat(红帽) - Fedora Directory Server
- Siemens(西门子) - DirX Server
- Sun - iPlanet Directory Server
此外还有开源/自由软件的实现——如Open LDAP、Apache HTTP Server使用代理服务器(通过模块mod_proxy)支持LDAP。
查询用户信息
技术选型
微软Windows活动目录的目录服务还是通过微软的技术框架来实现,无论从安全性和稳定性上都会有一定的保证,所以我们采用C#,当然你也可以使用C++实现,相信会有更好的性能提升。
目录服务程序集
这里我们介绍一下目录服务相关的程序集:
名称 | 说明 |
---|---|
System.DirectoryServices | 利用System.DirectoryServices命名空间,可以方便地从托管代码中访问AD域服务。 该命名空间包含两个组件类,即DirectoryEntry和DirectorySearcher,它们使用AD服务接口 (ADSI) 技术。 ADSI是Microsoft 提供的一组接口,作为使用各种网络提供程序的灵活的工具。 无论网络有多大,ADSI 都可以使管理员能够相对容易地定位和管理网络上的资源。 |
System.DirectoryServices.AccountManagement | 命名空间提供了统一的访问和用户操作、计算机和组安全原则(在多个主要存储):活动目录域服务 (AD DS)、 活动目录轻量级目录服务 (AD LDS)和机器 SAM (MSAM)。 管理独立于 命名空间的目录对象。 |
System.DirectoryServices.ActiveDirectory | 命名空间提供一个围绕Microsoft AD服务任务构建的高级别抽象对象模型。AD服务概念(例如,林、域、站点、子网、分区和架构)是此对象模型的一部分。 |
System.DirectoryServices.Protocols | 命名空间提供在轻量目录访问协议 (LDAP) 3 版 (V3) 和目录服务标记语言 (DSML) 2.0 版 (V2) 标准中定义的方法。 |
两种方法的实现与比较
为了获得用户的目录信息,看来我们需要使用的是前两个程序集和名称空间。
使用System.DirectoryServices.AccountManagement获取用户信息示例:
public DirectoryEntry GetEntryByUsername(string username)
{
PrincipalContext ctx = new PrincipalContext(ContextType.Domain, domain);
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, username);
DirectoryEntry entry = user.GetUnderlyingObject() as DirectoryEntry;
return entry;
}
第一次运行花费时间630ms
还有一种方法是直接使用目录搜索
public SearchResult GetEntryByUsername(string username)
{
DirectorySearcher search = new DirectorySearcher();
search.Filter = $"(&(objectClass=user)(sAMAccountName={username}))";
SearchResult result = search.FindOne();
}
第一次运行花费时间355ms
而且后续处理的事件花费差异也很大,使用DirectoryEntry获得的对象,所有属性还需要按其结构进行遍历:
public static void ShowProperties(DirectoryEntry entry)
{
PropertyCollection props = entry.Properties;
foreach (string k in props.PropertyNames)
{
Console.WriteLine("{0}: {1}", k, props[k].Value);
if (props[k].Value is Array)
{
Array arr = (Array)props[k].Value;
foreach (object obj in arr)
{
Console.WriteLine(" Item: " + obj + " Type: " + obj.GetType().Name);
}
}
}
}
而通过DirectorySearcher查询,不但查询速度快,结果似乎也是直接缓存中读出来的,高效快速。
if (result != null)
{
// user exists, cycle through LDAP fields (cn, telephonenumber etc.)
ResultPropertyCollection fields = result.Properties;
foreach (String ldapField in fields.PropertyNames)
{
// cycle through objects in each field e.g. group membership
// (for many fields there will only be one object such as name)
foreach (Object myCollection in fields[ldapField])
Console.WriteLine(String.Format("{0,-20} : {1}",
ldapField, myCollection.ToString()));
}
}
所以这里推荐使用DirectorySearcher直接进行目录对象(不仅限于用户,还有组织单元、计算机、其它设备等信息)的搜索和详细信息输出,效率会提升不少。
用途
利用Microsoft目录服务管理的公司,可以通过目录属性进行网络、设备等进行基于角色的访问控制,通过不同的AD组或设置目录属性,采用不同的管理策略。而IT经常需要对此过程进行自动化处理,所以通过LDAP进行目录服务数据的更改和访问就必不可少,还可以自动化权限(AD组、属性)的复查流程,减少组织和企业管理的人工成本。
C#通过LDAP访问目录服务的更多相关文章
- LDAP目录服务
LDAP目录服务 1.ldap目录服务介绍: 目录是一类为了浏览和搜索数据而设计的特殊的数据库,目录服务是按树状形式存储信息的,目录包含基于属性的描述信息,并且支持高级的过滤功能,一般来说,目录不支持 ...
- 轻型目录访问协议 ldap 公司内部网站的登录 单点登录
https://zh.wikipedia.org/wiki/轻型目录访问协议 轻型目录访问协议(英文:Lightweight Directory Access Protocol,缩写:LDAP,/ˈɛ ...
- LDAP未授权访问学习
LDAP未授权访问学习 一.LDAP 介绍 LDAP的全称为Lightweight Directory Access Protocol(轻量级目录访问协议), 基于X.500标准, 支持 TCP/IP ...
- JNDI 与 LDAP
对于众多接口服务.协议.互联网名称,总会遇到感到熟悉,但是时间一长就会忘记,所以还是要自己整理一下,加强记忆,当然最好的方式还是动手实践. JNDI : 全称:JAVA NAMING AND Dire ...
- java访问ad域
1.活动目录(AD) Active Directory 是用于 Windows Server 的目录服务.它存储着网络上各种对象的有关信息,并使该信息易于管理员和用户查找及使用.Active Dire ...
- Spring Security LDAP简介
1.概述 在本快速教程中,我们将学习如何设置Spring Security LDAP. 在我们开始之前,了解一下LDAP是什么? - 它代表轻量级目录访问协议.它是一种开放的,与供应商无关的协议,用于 ...
- Ldap 从入门到放弃(一)
OpenLDAP 2.4版本 快速入门 本文内容是自己通过官网文档.网络和相关书籍学习和理解并整理成文档,其中有错误或者疑问请在文章下方留言. 一.Introduction to OpenLDAP D ...
- GJM :用JIRA管理你的项目(三)基于LDAP用户管理 [转载]
感谢您的阅读.喜欢的.有用的就请大哥大嫂们高抬贵手"推荐一下"吧!你的精神支持是博主强大的写作动力以及转载收藏动力.欢迎转载! 版权声明:本文原创发表于 [请点击连接前往] ,未经 ...
- java 访问活动目录代码
package demo; import java.util.Hashtable; import javax.naming.Context; import javax.naming.NamingEnu ...
随机推荐
- 前端vue下载文件时blob返回流中怎么获取文件名
我很久之前写了一篇前端vue利用blob对象下载文件,有些人私信我,如果后端返回流失败,给出的json对象该怎么获得?前端获取的流怎么能获取原文件名?其实在那篇文章之后,我就已经针对这两个问题进行了优 ...
- docker 搭建php 开发环境 添加扩展redis、swoole、xdebug
docker-compose搭建lnmp 先决条件 首先需要安装docker 安装docker-compost 1.创建lnmp工作目录 #创建三个目录 mkdir lnmp && c ...
- MySQL中使用IN会不会走索引
结论:IN肯定会走索引,但是当IN的取值范围较大时会导致索引失效,走全表扫描 navicat可视化工具使用explain函数查看sql执行信息 场景1:当IN中的取值只有一个主键时 我们只需要注意一个 ...
- java后端工程师学习路线
根据自己的经历和见识梳理了一份java后端工程师的学习路线(不含安卓方向),难免有局限性和疏漏,请在评论区反馈意见和建议! 很明显的是我的学习路线过于庞大了[尴尬],你可以认为这些只是我的一家之言,具 ...
- tp 5 实现邮件发送
参考博客: https://www.cnblogs.com/ccdr/p/14751548.htmlhttps://www.cnblogs.com/ccdr/p/14751548.html 1:qq邮 ...
- 1251-Client does not support authentication protocol requested by server; consider upgrading MySQL client。
三:出现的一个错误在安装完MySQL的时候,我们现在一般都使用Navicat来连接数据库,可惜出现下面的错误:1251-Client does not support authentication p ...
- lgP6232题解
评蓝过分了吧,这题最多黄( 首先我们从挂钩的最上层向下走,假设这个挂杆的左边和右边一共有 \(k\) 件衣服. 若 \(k\) 是 \(2\) 的倍数,那么我们只能向左走(左边和右边的衣服一样多).反 ...
- Go值类型和引用类型+作用域+空白标识符+常量
值类型和引用类型 所有像 int.float.bool 和 string 这些基本类型都属于值类型,使用这些类型的变量直接指向存在内存中的值: 当使用等号 = 将一个变量的值赋值给另一个变量时,如:j ...
- 原生 JS 实现 HTML 转 Markdown,以及其实现逻辑
之前因为一些需要,需要转换部分 HTML 标签成 markdown 格式,但是不知不觉就完善到一个相对完整的函数. 然后我就封装成了一个文件放在了 github ,也简单做了两个示例网页. HTML ...
- ArcMap操作随记(9)
1.类似PS中功能的工具 [镜像要素].[比例].[延伸] 2.快速获得栅格统计参数 [获取栅格属性]工具 3.[编辑器][创建要素][构造工具] 可以右键,输入半径等参数 4.计算面的角度 [计算面 ...