设为首页收藏本站language 语言切换
查看: 1304|回复: 0
收起左侧

通过.NET Framework访问活动目录

[复制链接]
发表于 2010-2-25 10:25:19 | 显示全部楼层 |阅读模式
<p >System.DirectoryServices使用户能够通过ASP.NET访问一些基本的用户管理功能。这篇文章首先回顾了活动目录(AD)的有关概念,然后简要地讨论了实际的System.DirectoryServices名字空间本身,最后给出了可供我们在实际应用程序中使用的代码。<p ><center><font color="#000099"><strong>活动目录是什么?</strong></font></center><p >在目前的网络环境下,能够方便地控制对各个网络设备的访问是非常关健的。在控制谁在何时有访问何种设备的权限时,需要有一整套方法,这些设备包括打印机、文件以及其他的局域网或分布式网络资源。AD能够提供这些功能,由于与操作系统的整合非常紧密,这意味着AD能够在非常低的级别上提供支持。<p ><center><font color="#000099"><strong>AD的工作原理</strong></font></center><p >单地说,AD就是一个内容为所有网络资源、分层次、面向对象的数据库。最顶层的对象一般是Organization (O),在该组织单元(OU)之下是容器,最后是包含实际资源的对象。这种分层次的格式为系统管理人员创建了一种熟悉和易于管理的“树”。例如,如果指定一个OU访问一个实际的资源,这一权限也将被赋予包含在其中的对象。<p ><center><font color="#000099"><strong>如何创建AD?</strong></font></center><p >在.NET Framework中,微软为我们提供了System.DirectoryServices名字空间,它又使用了活动目录服务接口(ADSI)。<p >DSI是通过编程与许多不同的目录服务提供者交互的方式,也就是一种编程接口。<p >System.DirectoryServices空间中的类能够与如下所示的活动目录服务提供者配合使用:<p ><center>表1.1 AD服务提供者</center><p ><center><ccid_nobr><table border="1" class="content" width="502"><tr><td>目录服务提供者</td><td>路径</td></tr><tr><td>Windows NT 5.0、Windows 2000或Windows XP</td><td>WinNT://path</td></tr><tr><td>Lightweight Directory Access Protocol (LDAP)</td><td>LDAP://path</td></tr><tr><td>Novell NetWare Directory Service</td><td>NDS://path</td></tr><tr><td>Novell Netware 3.x</td><td>NWCOMPAT://path</td></tr><tr><td>Internet Information Services (IIS)</td><td>IIS://</td></tr></table></ccid_nobr></center><p >在System.DirectoryServices名字空间内,有二个主要的类:System.DirectoryServices.DirectoryEntry和System.DirectoryServices.DirectorySearcher类。本篇文章不涉及这二个类的细节,需要注意的是,DirectorySearcher只能与LDAP提供者一起使用。<p >在使用DirectoryEntry对象时,每个对象都有一个模式。模型是对象条目的类型。例如,如果有一个User模式的DirectoryEntry对象,它就代表是一个用户。<p >在本篇文章中,我们使用了Windows 2000提供者(WinNT://)和System.DirectoryServices.DirectoryEntry类。<p ><center><font color="#000099"><strong>用户管理</strong></font></center><p >在本篇文章的例子中,我们使用System.DirectoryServices名字空间创建一个数据访问层(DAL),执行一些非常基础的用户管理任务。DAL是对执行数据访问的真实的复杂性进行抽象的一种方法。例如,如果我们要编写一个访问Access数据库的DAL,就可以在对象中隐藏所有与ADO.NET有关的任务。当开发人员需要与数据库打交道时,只需要简单地使用这些对象,而无需关心特定的实现细节。开发者根本无需为ADO.NET操心,即使是以后决定升级到SQL Server,也只是需要改变DAL,使之适合新的数据库即可,其他的东西无需改变。<p ><center><font color="#000099"><strong>用户对象</strong></font></center><p >我们建立的第一个对象用来表示任何给定用户的当前状态,该对象对User模式的DirectoryEntry类进行抽象。为了清楚起见,它看起来更象一个实际的User对象。<p ><ccid_nobr><table align="center" border="1" bordercolordark="#FFFFFF" bordercolorlight="black" cellpadding="2" cellspacing="0" width="550"><tr><td bgcolor="e6e6e6" class="code"><pre><ccid_code>namespace DSHelper {  public class DSUser {    public DSUser(System.DirectoryServices.DirectoryEntry user) {      this.domainName=user.Path;      this.Username=user.Name;      this.Password=user.Password;      try {        this.FullName=Convert.ToString(user.Invoke(&amp;quot;Get&amp;quot;, new object[] {&amp;quot;FullName&amp;quot;}));        this.Description=Convert.ToString(user.Invoke(&amp;quot;Get&amp;quot;, new object[] {&amp;quot;Description&amp;quot;}));        this.PasswordExpired=Convert.ToInt32(user.Invoke(&amp;quot;Get&amp;quot;, new object[] {&amp;quotasswordExpired&amp;quot;}));        this.RasPermissions=Convert.ToInt32(user.Invoke(&amp;quot;Get&amp;quot;, new object[] {&amp;quot;RasPermissions&amp;quot;}));        this.MaxStorage=Convert.ToInt32(user.Invoke(&amp;quot;Get&amp;quot;, new object[] {&amp;quot;MaxStorage&amp;quot;}));        this.PasswordAge=Convert.ToInt32(user.Invoke(&amp;quot;Get&amp;quot;, new object[] {&amp;quotasswordAge&amp;quot;}));        this.HomeDirectory=Convert.ToString(user.Invoke(&amp;quot;Get&amp;quot;, new object[] {&amp;quot;HomeDirectory&amp;quot;}));        this.LoginScript=Convert.ToString(user.Invoke(&amp;quot;Get&amp;quot;, new object[] {&amp;quot;LoginScript&amp;quot;}));        this.HomeDirDrive=Convert.ToString(user.Invoke(&amp;quot;Get&amp;quot;, new object[] {&amp;quot;HomeDirDrive&amp;quot;}));        this.userDirEntry=user;      }catch(Exception e) {        throw(new Exception(&amp;quot;Could not load user from given DirectoryEntry&amp;quot;));      }    }    public DSUser(string Username, string Password, string DomainName) {      domainName=DomainName;      if(domainName==&amp;quot;&amp;quot; || domainName==null) domainName=Environment.MachineName;      username=Username;      password=Password;    }    private object groups=null;    public object Groups{get{return groups;} set{groups=value;}}  }}</ccid_code></pre></td></tr></table></ccid_nobr><p ><center>图1.2 User对象</center><p >我们的用户对象有二个缺省的构造器。第一个用来用一个给定的DirectoryEntry对象对我们的用户进行初始化,它将使用Invoke方法从对象中“获取”用户的属性。<p >第二个构造器用来创建一个新的用户。我们只需要向它传递三个参数,在用来创建新用户时,它就会创建一个新的DSUser对象。需要注意的是,由于没有完成任何的AD操作,因此我们并没有在AD中创建真正的用户。<p ><center><font color="#000099"><strong>数据访问层(DAL)</strong></font></center><p >下一步就是创建AD的DAL封装了,下面的一些代码是分步骤完成的完整的UserAdmin DAL代码。<p >我们首先创建并初始化在UserAdmin类中所需要的代码:<p ><ccid_nobr><table align="center" border="1" bordercolordark="#FFFFFF" bordercolorlight="black" cellpadding="2" cellspacing="0" width="550"><tr><td bgcolor="e6e6e6" class="code"><pre><ccid_code>#缺省属性的初始化    //我们的错误日志设备,应当尽量保持简单,避免代码膨胀过大    System.Text.StringBuilder errorLog = new System.Text.StringBuilder();    private System.Boolean error=false;    public System.Boolean Error{get{return error;}}    public string ErrorLog{get{return errorLog.ToString();}}    //设置缺省的属性    private string loginPath=&amp;quot;WinNT://&amp;quot;+Environment.MachineName+&amp;quot;,computer&amp;quot;;    private string domainName=null;    private string loginUsername=null;    private string loginPassword=null;    private System.DirectoryServices.AuthenticationTypes authenticationType = System.DirectoryServices.AuthenticationTypes.None;    private System.DirectoryServices.DirectoryEntry AD=null;    private System.Boolean connected=false;    #endregion</ccid_code></pre></td></tr></table></ccid_nobr><p ><center>图1.3 缺省属性的初始化</center><p >注意我们是如何将LoginPath硬拷贝为WinNT提供商的。为了使DAL能够与任何其他AD服务提供商配合,这一点必须进行改变。另外需要注意的是,我使用了System.Text.StringBuilder对象来保存错误日志,从而简化了错误处理过程。在有错误发生的情况下,系统会简单地添加一条日志,Boolean型变量error将会被设置为“真”值。下面的代码是我们设计的类的构造器:(图1.4)<p ><ccid_nobr><table align="center" border="1" bordercolordark="#FFFFFF" bordercolorlight="black" cellpadding="2" cellspacing="0" width="550"><tr><td bgcolor="e6e6e6" class="code"><pre><ccid_code>#region .ctor's    public UserAdmin() {      Connect();    }    /// &amp;lt;摘要&amp;gt;    /// 在需要的时候,使我们能够创建UserAdmin类    /// &amp;lt;/摘要&amp;gt;    /// &amp;lt;param name=&amp;quot;LoginUsername&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;    /// &amp;lt;param name=&amp;quot;LoginPassword&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;    /// &amp;lt;param name=&amp;quot;AuthenticationType&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;    /// &amp;lt;param name=&amp;quot;DomainName&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;    public UserAdmin(string LoginUsername, string LoginPassword,                System.DirectoryServices.AuthenticationTypes AuthenticationType, string DomainName) {      loginUsername=LoginUsername;      loginPassword=LoginPassword;      authenticationType=AuthenticationType;      if(DomainName==&amp;quot;&amp;quot; || DomainName==null) DomainName=System.Environment.UserDomainName;      domainName=DomainName;      Connect();    }    /// &amp;lt;摘要&amp;gt;    /// 获得UserAdmin类的另一种方式,可以指定另外一个LoginPath,例如LDAP或IIS。    /// &amp;lt;/摘要&amp;gt;    /// &amp;lt;param name=&amp;quot;LoginPath&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;    /// &amp;lt;param name=&amp;quot;LoginUsername&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;    /// &amp;lt;param name=&amp;quot;LoginPassword&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;    /// &amp;lt;param name=&amp;quot;AuthenticationType&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;    /// &amp;lt;param name=&amp;quot;DomainName&amp;quot;&amp;gt;&amp;lt;/param&amp;gt;    public UserAdmin(string LoginPath, string LoginUsername, string LoginPassword,                System.DirectoryServices.AuthenticationTypes AuthenticationType, string DomainName) {      loginPath=LoginPath;      loginUsername=LoginUsername;      loginPassword=LoginPassword;      authenticationType=AuthenticationType;      if(DomainName==&amp;quot;&amp;quot; || DomainName==null) DomainName=System.Environment.UserDomainName;      domainName=DomainName;      Connect();    }    #endregion</ccid_code></pre></td></tr></table></ccid_nobr><p ><center>图1.4 构造器</center><p align="center"><font color="FF0000" >1</font>2<span class="content01">下一页&gt;&gt;</span></p></p>
您需要登录后才可以回帖 登录 | 论坛注册

本版积分规则

QQ|Archiver|手机版|小黑屋|sitemap|鸿鹄论坛 ( 京ICP备14027439号 )  

GMT+8, 2025-4-10 13:15 , Processed in 0.205761 second(s), 24 queries , Redis On.  

  Powered by Discuz!

  © 2001-2025 HH010.COM

快速回复 返回顶部 返回列表