要用代码访问 Active Directory域服务,需引用System.DirectoryServices命名空间,该命名空间包含两个组件类,DirectoryEntry和 DirectorySearcher。DirectoryEntry类可封装 ActiveDirectory域服务层次结构中的节点或对象,使用此类绑定到对象、读取属性和更新特性;使用DirectorySearcher类可对 Active Directory域服务层次结构执行查询。

如果仅要对AD的组织单元,群组和用户进行查询或者更改属性,使用上述两个类即可。下面给出的是查询在AD中某个组织单元下的所有用户部分代码:

DirectoryEntry objDE = new DirectoryEntry(strADRootPath, strADAccount, strADPassword);
string strFilter = "(&(objectCategory=person)(objectClass=user))";
DirectorySearcher objSearcher = new DirectorySearcher(objDE, strFilter);
//排序
objSearcher.Sort = new SortOption("name", SortDirection.Ascending);
SearchResultCollection src = objSearcher.FindAll();

其中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用户的账户和密码,如果是管理员则可以进行任何操作,普通只能进行查询操作。

执行上述代码即可获取到在某个指定组织单元的所有用户,搜索结果存放在src中,要读取用户属性值可使用下面代码:

//获取用户的名称和账户
foreach (SearchResult sr in src)
{
  strUserName=sr.Properties["name"][].ToString();
  strUserName= sr.Properties["userPrincipalName"][].ToString();
}

值得注意的是因为在创建AD用户的时候填写的用户信息不同,每个AD用户所具有的属性都不一定相同,建议使用如下方法进行取值:

if (sr.Properties.Contains("sn"))
{
strFirstName = sr.Properties["sn"][].ToString();//姓
}
if (sr.Properties.Contains("givenName"))
{
strLastName = sr.Properties["givenName"][].ToString();//名
}

要知道一个用户的所有属性可使用如下代码:

foreach (string strPropNamein sr.Properties.PropertyNames)
{
Console.WriteLine(strPropName);
}

还有一种读取AD用户属性字段值的方法:

foreach (SearchResult sr in src)
{
DirectoryEntry myde = sr.GetDirectoryEntry();
strGuid = myde.Guid.ToString();//用户Guid,创建用户时由系统自动生成
strParentGuid = myde.Parent.Guid.ToString();//用户所在组织单元的Guid
myde.Properties["name"][].ToString();//用户名称
}

同样的,如果要得到是AD组织单元或者群组的话也是这么做,对应于组织单元筛选字符串可以这么写:

//字符筛选器,筛选类型为OU的对象
string strFilter = "(&(objectCategory=organizationalUnit)(objectClass=organizationalUnit))";

群组的筛选字符串:

string strFilter = "(&(objectCategory=group)(objectClass=group))";  

上面是对AD的查询操作,如果查询之后需要修改,仅需要做些许变动,下面是修改用户属性部分代码:

foreach (SearchResult sr in src)
{
string strUserName = sr.Properties["name"][].ToString();
//targetUserName:要修改用户名称
if (strUserName.Equals(targetUserName))
{
DirectoryEntryde = sr.GetDirectoryEntry();
de.Properties["sn"].Value = m_User.FirstName;//姓
de.Properties["givenName"].Value = m_User.LastName;//名
de.Properties["mobile"].Value = m_User.Mobile;//移动电话
de.CommitChanges();
}
}

修改AD组织单元或者群组也是用类似的方法。值得注意的是,在AD中有些属性是拒绝修改的,一旦修改了不允许修改的属性,会被服务器拒绝或者出现服务器不愿意执行该操作异常。

若要向AD中添加用户,组织单元或者群组的话也是需要通过DirectoryEntry来添加,如下是向AD的指定路径添加一个用户:

public bool AddUser2AD(string strUserName, string strSAMAccountname,
string strPassword, string strPath)
{
string strname = "CN=" + strUserName;
try
{
// strADAccount ,strADPassword为AD管理员账户和密码
DirectoryEntry objDE = new DirectoryEntry(strPath, strADAccount, strADPassword);
DirectoryEntries objDES = objDE.Children;
DirectoryEntry myDE = objDES.Add(strname, "User");
myDE.Properties["userPrincipalName"].Value = strSAMAccountname;
myDE.Properties["name"].Value = strUserName;
myDE.Properties["sAMAccountName"].Value = strSAMAccountname;
myDE.CommitChanges(); //设置密码
IADsUser objUser = myDE.NativeObject as IADsUser;
objUser.SetPassword(strPassword);
//设置用户状态:密码永不过期(65536)+用户正常(512)= 66048
objUser.Put("userAccountControl", );
objUser.SetInfo();
}
catch
{
return false;
}
return true;
}

特别要注意最后几行设置用户密码和账户状态代码。如果myDE.CommitChanges()后面的代码没有;,那么在AD里面创建的用户是禁用状态,并且密码为空。如果在AD中直接写:

myDE.Password = strPassword;
myDE.Properties["userAccountControl"].Value = ;

是会失败的。这里我们可以利用ActiveDs.dll。ActiveDs是一个AD服务相关应用程序COM接口,里面提供了设置密码,修改密码,获取属性值的一些方法。按照如上写法即可创建正常的AD用户,切用户密码永不过期。

解释一下userAccountControl,该属性记录了用户的AD账号信息,是一组16进制数,该属性标志是累积性的。若要禁用用户的帐户,将userAccountControl属性设置为 0x0202 (0x002 + 0x0200)。在十进制中,它是 514 (2 + 512);若要启用账户且密码永不过期,请将 userAccountControl属性设置为 0x10200 (0x10000 + 0x0200),十进制为66048。

若想要修改用户密码的话也可以使用ActiveDs提供的方法:

DirectoryEntry obj = sr.GetDirectoryEntry();
IADsUser objUser = obj.NativeObject as IADsUser;
objUser.ChangePassword(strOldPassword, strNewPassword);
objUser.SetInfo();

最后提供一个验证AD用户身份的方法以资参考:

/// <summary>
///验证用户登录
///</summary>
///<param name="strUserAccount">用户账户</param>
///<param name="strPassword">用户密码</param>
///<returns>验证通过则返回true,否则返回false</returns>
public static bool VerifyUserLogin(string strUserAccount, stringstrPassword)
{
try
{
// strADRootPath为该组织单元路径
DirectoryEntry objDE = newDirectoryEntry(strADRootPath, strUserAccount, strPassword);
DirectorySearcher objSerach = new DirectorySearcher(objDE);
SearchResult sr = objSerach.FindOne();
return true;
}
catch
{
return false;
}
}

原文地址:http://blog.csdn.net/dl020840504/article/details/10200227

其他文章推荐:http://www.cnblogs.com/springyangwc/archive/2012/02/07/2340987.html

【转】 如何利用C#代码来进行操作AD的更多相关文章

  1. 如何利用CSS代码使图片和文字在同一行显示且对齐

    对于初学css的新手朋友来说,经常会遇到这样一个问题,当文字和图片出现在同一行或者同一个div里面的时候,在浏览器中运行出来的显示效果往往是在不同的行,那么,我们怎么才能利用CSS代码使图片和文字在同 ...

  2. 利用Python代码编写计算器小程序

    import tkinter import tkinter.messagebox import math class JSQ: def __init__(self): #创建主界面 self.root ...

  3. Android手机上,利用bat脚本模拟用户操作

    ………… 那么你就可以来看看这篇帖子了. 言归正传 利用bat脚本模拟用户操作,需要用到两点: ①就是adb命令了,adb命令可以用来模拟用户在手机上的操作 ②bat语言,就是批处理语言,主要用来进行 ...

  4. JDBCToolsV2:利用ThreadLocal保证当前线程操作同一个数据库连接对象。

    JDBCToolsV2:     利用ThreadLocal保证当前线程操作同一个数据库连接对象. package com.dgd.test; import com.alibaba.druid.poo ...

  5. 利用Java代码在某些时刻创建Spring上下文

    上一篇中,描述了如何使用Spring隐式的创建bean,但当我们需要引进第三方类库添加到我们的逻辑上时,@Conponent与@Autowired是无法添加到类上的,这时,自动装配便不适用了,我们需要 ...

  6. 我利用网上代码开发的JQuery图片插件

    我利用网上代码开发的JQuery图片插件 代码如下 (function($){ $.fn.FocusPic = function(options){ var defaults = { interval ...

  7. ligerui_ligerTree_002_利用JavaScript代码配置ligerTree节点

    利用JavaScript代码配置ligerTree节点: 源码地址:http://download.csdn.net/detail/poiuy1991719/8571255 效果图: <%@ p ...

  8. JDBC最原始的代码做查询操作

    首先编写一个User类. public class User { private String username; private String password; public String get ...

  9. C# 一些代码小结--UI操作

    C# 一些代码小结--UI操作 使用控件名调用控件 object obj = this.GetType().GetField("控件名", System.Reflection.Bi ...

随机推荐

  1. 哇塞!HTML5 实现的雨滴效果 CSS发抖

    http://dreamsky.github.io/main/blog/rainy-day/ Rainy Day – 哇塞! HTML5 实现的雨滴效果 http://www.webhek.com/m ...

  2. [elk]停电日志离线恢复故障处理-elk环境极速搭建

    es数据手动导入 周末停电了两天,发现两天的日志没导入: 原因: 1. elk开启没设启动 2.日志入库时间是当前时间,不是日志本身的time字段 - 导入步骤 1. 先把日志拖下来 2. 事先需要干 ...

  3. Re-ID with Triplet Loss

    一篇讲Person Re-ID的论文,与人脸识别(认证)有非常多相通的地方. 文章链接: <In Defense of the Triplet Loss for Person Re-Identi ...

  4. ntp服务的细节全解析

    在linux里设置NTP服务并不难,但是NTP本身确是一个很复杂的协议. 你都了解细节么? 1. 时间和时区 date命令可显示时间与市区 [root@T_PV1_DB ~]# date Tue Fe ...

  5. AI落地企业业务的一些问题

    这两年大家都在喊未来已来,软件企业不管有没有算法工程师都竖起了AI的大旗,传统企业不管现在OA现状如何都想在数据转型.智能制造.机器智能方面尝尝鲜,感觉好像和前两年的互联网+风潮有点像,最近半年我在某 ...

  6. 【HBase】Rowkey设计【转】

    本章将深入介绍由HBase的存储架构在设计上带来的影响.如何设计表.row key.column等等,尽可能地使用到HBase存储上的优势. Key设计 HBase有两个基础的主键结构:row key ...

  7. eclipse memory内存溢出

    eclipse 跑web程序时候 内存溢出..解决方式 设置 jvm内存分配方案: -Xms800m -Xmx800m -XX:MaxNewSize=256m -XX:MaxPermSize=256m

  8. ID、Class和标签选择器优先级

    按一般论:ID > Class > 标签 1.如以下样式: <div id="id" class="class">选择器优先权</ ...

  9. 实战入侵(突破FCK+安全狗上传)

    PS:有点尴尬,二次上传突破FCK,免杀马儿过狗. 刚开始和超霸一起弄,TMDGB.弄到四点多,早上尼玛七点多的又去考试,虽然考试还是睡着了,但是TMDGB感觉日子好充实啊! FCK上传地址如下所示: ...

  10. [转]关闭word进程

    命名空间 :System.Diagnostics 以前在word的时候,经常碰到word进程产生一大堆,怕关错了,把用户自己打开的word也关闭,一直搞忽悠,今天上网花了10块钱,下了个文件,给我了一 ...