C#操作Active Directory(AD)详解
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(组织-公司)
- ou – organization unit(组织单元-部门)
- c - countryName(国家)
- dc - domainComponent(域名)
- sn – suer name(真实名称)
- cn - common name(常用名称)
3.常见的目录服务软件
- X.500
- LDAP
- Actrive Directory,Microsoft公司
- NIS
4.AD介绍
.Net提供了专用类操作AD,本文详细介绍使用C#操作AD的方法。
一、系统环境
系统环境:Windows Server 2008 R2, VS2010, .Net Framework 4.0
AD Server:LDAP的server IP
基本DN:OU=user,DC=Company,DC=com
用来登录的管理员:Peter
密码:ab#CD%1234
二、程序
1. 引用
.Net操作AD的类在命名空间System.DirectoryServices下,需要将该类引用进来。
2. 连接
要操作AD需首先连接AD,就象要操作数据先要连接数据库一样。
其中ADPath是要查询组织单元的所在的LDAP,其格式为:LDAP:\\ OU=XX部门,OU=XX公司,DC=域名,DC=COM,如果连接到的AD是在服务器上那么格式写成LDAP:\\XX.XX.XX.XX\ OU=XX部门,OU=XX公司,DC=域名,DC=COM(XX.XX.XX.XX为服务器IP);ADAccount和ADPwd为AD用户的账户和密码,如果是管理员则可以进行任何操作,普通只能进行查询操作。
de.Path = "LDAP://AD服务器地址/OU=CompanyA,DC=contoso,DC=com";
de.Username = @"contoso\管理员账号";
de.Password = "管理员密码";
private static string DomainName = "VMEX";
private static string LDAPDomain = "DC=VMEX,DC=local";
private static string ADPath = "LDAP://DC=VMEX,DC=local";
//AD管理员帐号
private static string ADUser = "Administrator";
//AD管理员密码
private static string ADPasssWord = "1234@abcd";
/// <summary>
/// 获得DirectoryEntry对象实例,以管理员登陆AD
/// </summary>
/// <returns></returns>
private static DirectoryEntry GetDirectoryObject()
{
DirectoryEntry entry = null;
try
{
entry = new DirectoryEntry("LDAP://10.10.10.16", "Peter", " ab#CD%1234", AuthenticationTypes.Secure);
}
catch (Exception ex)
{
}
return entry;
}
3. 查询
根据各种条件获取具体的用户。下例为根据公共名称获取对象。
/// <summary>
/// 根据用户公共名称取得用户的 对象
/// </summary>
/// <param name="commonName">用户公共名称</param>
/// <returns>如果找到该用户则返回用户的对象,否则返回 null</returns>
public static DirectoryEntry GetDirectoryEntry(string commonName)
{
DirectoryEntry de = GetDirectoryObject();
DirectorySearcher deSearch = new DirectorySearcher(de);
deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(cn=" + commonName.Replace("\\", "") + "))";
deSearch.SearchScope = SearchScope.Subtree;
try
{
SearchResult result = deSearch.FindOne();
de = new DirectoryEntry(result.Path);
return de;
}
catch (Exception ex)
{
return null;
}
}
4. 修改用户
修改查询到的Entity的值,修改后将修改记录保存到AD。注意有两种保存属性的方式。具体使用哪种请参考帮助。
1) 直接修改属性
2) 通过invoke来触发AD的内置函数
/// <summary>
/// 修改查询到的用户
/// </summary>
/// <param name="CommonName">通用名(displayName,系统中显示的中文字)</param>
/// <param name="Account">帐户名(如Peter)</param>
/// <param name="organizeName">组织单元名(资讯中心)</param>
/// <param name="password">密码</param>
public static string ChangeADAccount(string CommonName, string Account, string password)
{
//获取对应AD实体
DirectoryEntry user = GetDirectoryEntry( commonName);
try
{
ADHelper.SetProperty(user, " sAMAccountName ", Account);
user.Invoke("SetPassword", new object[] { password });
user.CommitChanges();
}
catch (Exception e)
{
throw e;
}
return user.Path;
} /// <summary>
/// 设置指定的属性值
/// </summary>
/// <param name="de"></param>
/// <param name="propertyName">属性名称?</param>
/// <param name="propertyValue">属性值</param>
public static void SetProperty(DirectoryEntry de, string propertyName, string propertyValue)
{
if (de.Properties.Contains(propertyName))
{
if (String.IsNullOrEmpty(propertyValue))
{
de.Properties[propertyName].RemoveAt(0);
}
else
{
de.Properties[propertyName][0] = propertyValue;
}
}
else
{
if (!String.IsNullOrEmpty(propertyValue))
{
de.Properties[propertyName].Add(propertyValue);
}
}
}
5. 修改OU
1) 获取OU
DirectoryEntry OUEntry = new DirectoryEntry(GetOrganizeNamePath(OUName), "Peter", " ab#CD%1234", AuthenticationTypes.Secure);
/// <summary>
/// 获得OU的Path
/// </summary>
/// <param name="organizeUnit">OU名</param>
/// <returns></returns>
public static string GetOrganizeNamePath(string organizeUnit)
{
StringBuilder sb = new StringBuilder();
sb.Append(ADPath);
sb.Append("/");
return sb.Append(SplitOrganizeNameToDN(organizeUnit)).ToString();
}
2) 修改OU项
OUEntry.Rename("OU=" + newOUName);
OUEntry.CommitChanges();
3) 删除OU
DirectoryEntry OUParent = OUEntry.Parent;
OUParent.Children.Remove(OUEntry);
OUParent.CommitChanges();
6. 修改组
1) 获取组
/// <summary>
/// 获取AD组
/// </summary>
/// <param name="groupName"></param>
/// <param name="organizeUnit"></param>
/// <returns></returns>
public static DirectoryEntry GetADGroupInOU(string groupName, string organizeUnit)
{
if (!String.IsNullOrEmpty(groupName))
{
DirectoryEntry de = new DirectoryEntry(GetOrganizeNamePath(organizeUnit) , "Peter", " ab#CD%1234", AuthenticationTypes.Secure); ;
DirectorySearcher deSearch = new DirectorySearcher(de);
deSearch.Filter = "(&(objectClass=group)(cn=" + groupName.Replace("\\", "") + "))";
deSearch.SearchScope = SearchScope.Subtree;
try
{
SearchResult result = deSearch.FindOne();
if (result != null)
{
de = new DirectoryEntry(result.Path, adminName, adminPassword);
}
else
{
return null;
}
return de;
}
catch (Exception ex)
{
return null;
}
}
else
{
return null;
}
}
2) 管理组成员
group.Properties["member"].Add(user.Properties["distinguishedName"].Value); group.Properties["member"].Remove(user.Properties["distinguishedName"].Value);
三、查看AD User属性结果
在程序中修改了User属性后我们要检验一下是否被修改了,有三种方式查看AD中User属性:
1. Active Directory Users and Computers
打开Active Directory Users and Computers,选择一个用户,右键单击该用户选择属性显示如下图所示的属性页。在该属性页只能看到一些常用的属性。

2. Exchange Management Console
打开Exchange Management Console,选择一个用户,右键单击该用户选择属性显示如下图所示的属性页。单击Customer Attributes按钮可以查看自定义的属性。

3. adsiedit.msc
以上两种方式所看到的属性都不全,要看到所有属性需使用adsiedit.msc工具。
在运行窗口中输入adsiedit.msc后打开本工具。选择一个用户,右键单击该用户选择属性显示如下图所示的属性页。

C#操作Active Directory(AD)详解的更多相关文章
- C#操作SQLite方法实例详解
用 C# 访问 SQLite 入门(1) CC++C#SQLiteFirefox 用 C# 访问 SQLite 入门 (1) SQLite 在 VS C# 环境下的开发,网上已经有很多教程.我也是从 ...
- 使用Java操作文本文件的方法详解
使用Java操作文本文件的方法详解 摘要: 最初java是不支持对文本文件的处理的,为了弥补这个缺憾而引入了Reader和Writer两个类 最初java是不支持对文本文件的处理的,为了弥补这个缺憾而 ...
- Python操作redis字符串(String)详解 (三)
# -*- coding: utf-8 -*- import redis #这个redis不能用,请根据自己的需要修改 r =redis.Redis(host=") 1.SET 命令用于设置 ...
- How to setup Active Directory (AD) In Windows Server 2016
Windows Server 2016 is the newest server operating system released by Microsoft in October 12th, 201 ...
- 操作Active Directory C#
.Net平台操作活动目录Active Directory,使用System.DirectoryServices.ActiveDirectory,主要是User OU 和Group的操作. 代码运行了一 ...
- datazen Active Directory AD 配置
今天苦心经营的datazen 链接AD,文档已经无法吐槽了简单的几句话,根本不够用. 先说一下链接AD 的好处吧, 1 首先免去设置密码的麻烦,因为直接用AD账号的密码. 2 更安全,因为客户可不想自 ...
- Yii2.0数据库操作增删改查详解
1.简单查询: one(): 根据查询结果返回查询的第一条记录. all(): 根据查询结果返回所有记录. count(): 返回记录的数量. sum(): 返回指定列的总数. average(): ...
- thinkphp框架中“关联操作”的完整定义详解
在复杂的关联操作中,如果要给关联定义增加可选的属性,我们可以采用完整定义的方式. 完整定义的格式是: protected $_link = array( '关联表名1' => arr ...
- python数据库操作常用功能使用详解(创建表/插入数据/获取数据)
实例1.取得MYSQL版本 复制代码 代码如下: # -*- coding: UTF-8 -*-#安装MYSQL DB for pythonimport MySQLdb as mdbcon = Non ...
随机推荐
- js基础知识之_对象
javascript 对象 1.基于对象 一切皆对象,以对象的概念来编程 2.面向对象的编程(oop,Object oriented programming) 1.对象 就是人们要研究的任何事物,不仅 ...
- Synchronized vs SyncRoot
我们知道,在.net的一些集合类型中,譬如Hashtable和ArrayList,都有Synchronized静态方法和SyncRoot实例方法,他们之间有联系吗?我怎么才能用好他们呢?我们以Hash ...
- centos 彻底卸载mysql
yum remove mysql mysql-server mysql-libs compat-mysql51rm -rf /var/lib/mysqlrm /etc/my.cnf查看是否还有mysq ...
- 为什么用linear regression可以做classification
输出空间 错误衡量方式 能不能直接用linear regression for classification 当成一个分类器回传回去 heuristic(启发式的:试探) 错误衡量 complexit ...
- JavaScript学习心得(三)
一 变量 var:变量声明 变量名 =:赋值 简单值类型 全局变量:编程的一般规则——应用程序应该只完成必须的最少功能,如果一个变量不是绝对必需,就不该是全局:全局变量对维护性能不利,因为需要一直维护 ...
- CentOS 6.0 图文安装教程
CentOS 6.0下载地址:wget http://ftp.riken.jp/Linux/centos/6.0/isos/i386/CentOS-6.0-i386-bin-DVD.iso 下边就是安 ...
- Apriori算法在购物篮分析中的运用
购物篮分析是一个很经典的数据挖掘案例,运用到了Apriori算法.下面从网上下载的一超市某月份的数据库,利用Apriori算法进行管理分析.例子使用Python+MongoDB 处理过程1 数据建模( ...
- WPF Canvas小例子
源码下载:DraggingElementsInCanvas_demo.rar
- nutch 1.7 导入 eclipse
开发环境建议:ubuntu+eclipse (windows + cygwin + eclipse不推荐) 第一步:下载http://archive.apache.org/dist/nutch/从上述 ...
- python判断用户注册中用户名是否包含非法字符
class UserRegisterForm(ModelForm): role = forms.IntegerField() check_password = forms.CharField(requ ...