用C#做一个程序,能管理域用户帐号,包括,添中、删除、修改用户帐号,
谁能给这样的代码,100分就给他。

解决方案 »

  1.   

    我们建立的第一个对象用来表示任何给定用户的当前状态,该对象对User模式的DirectoryEntry类进行抽象。为了清楚起见,它看起来更象一个实际的User对象。 
       
      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("Get", new object[] 
      {"FullName"})); 
       this.Description=Convert.ToString(user.Invoke("Get", new object[] 
      {"Description"})); 
       this.PasswordExpired=Convert.ToInt32(user.Invoke("Get", new object[] 
      {"PasswordExpired"})); 
       this.RasPermissions=Convert.ToInt32(user.Invoke("Get", new object[] 
      {"RasPermissions"})); 
       this.MaxStorage=Convert.ToInt32(user.Invoke("Get", new object[] 
      {"MaxStorage"})); 
       this.PasswordAge=Convert.ToInt32(user.Invoke("Get", new object[] 
      {"PasswordAge"})); 
       this.HomeDirectory=Convert.ToString(user.Invoke("Get", new object[] 
      {"HomeDirectory"})); 
       this.LoginScript=Convert.ToString(user.Invoke("Get", new object[] 
      {"LoginScript"})); 
       this.HomeDirDrive=Convert.ToString(user.Invoke("Get", new object[] 
      {"HomeDirDrive"})); 
       this.userDirEntry=user; 
       }catch(Exception e) { 
       throw(new Exception("Could not load user from given DirectoryEntry")); 
       } 
       } 
       public DSUser(string Username, string Password, string DomainName) { 
       domainName=DomainName; 
       if(domainName=="" || domainName==null) domainName=Environment.MachineName; 
       username=Username; 
       password=Password; 
       } 
       private object groups=null; 
       public object Groups{get{return groups;} set{groups=value;}} 
       } 
      } 
       
       
       
       
      图1.2 User对象 
       
       
      我们的用户对象有二个缺省的构造器。第一个用来用一个给定的DirectoryEntry对象对我们的用户进行初始化,它将使用Invoke方法从对象中“获取”用户的属性。 
       
      第二个构造器用来创建一个新的用户。我们只需要向它传递三个参数,在用来创建新用户时,它就会创建一个新的DSUser对象。需要注意的是,由于没有完成任何的AD操作,因此我们并没有在AD中创建真正的用户。 
       
       
      数据访问层(DAL) 
       
       
      下一步就是创建AD的DAL封装了,下面的一些代码是分步骤完成的完整的UserAdmin DAL代码。 
       
      我们首先创建并初始化在UserAdmin类中所需要的代码: 
       
      #缺省属性的初始化 
       //我们的错误日志设备,应当尽量保持简单,避免代码膨胀过大 
       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="WinNT://"+Environment.MachineName+",computer"; 
       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 
       
       
       
       
      图1.3 缺省属性的初始化 
       
       
      注意我们是如何将LoginPath硬拷贝为WinNT提供商的。为了使DAL能够与任何其他AD服务提供商配合,这一点必须进行改变。另外需要注意的是,我使用了System.Text.StringBuilder对象来保存错误日志,从而简化了错误处理过程。在有错误发生的情况下,系统会简单地添加一条日志,Boolean型变量error将会被设置为“真”值。下面的代码是我们设计的类的构造器:(图1.4) 
       
      #region .ctor's 
       public UserAdmin() { 
       Connect(); 
       } 
       /// <摘要> 
       /// 在需要的时候,使我们能够创建UserAdmin类 
       /// </摘要> 
       /// <param name="LoginUsername"></param> 
       /// <param name="LoginPassword"></param> 
       /// <param name="AuthenticationType"></param> 
       /// <param name="DomainName"></param> 
       public UserAdmin(string LoginUsername, string LoginPassword, 
       System.DirectoryServices.AuthenticationTypes AuthenticationType, 
      string DomainName) { 
       loginUsername=LoginUsername; 
       loginPassword=LoginPassword; 
       authenticationType=AuthenticationType; 
       if(DomainName=="" || DomainName==null) 
      DomainName=System.Environment.UserDomainName; 
       domainName=DomainName; 
       Connect(); 
       } 
       /// <摘要> 
       /// 获得UserAdmin类的另一种方式,可以指定另外一个LoginPath,例如LDAP或IIS。 
       /// </摘要> 
       /// <param name="LoginPath"></param> 
       /// <param name="LoginUsername"></param> 
       /// <param name="LoginPassword"></param> 
       /// <param name="AuthenticationType"></param> 
       /// <param name="DomainName"></param> 
       public UserAdmin(string LoginPath, string LoginUsername, string LoginPassword, 
       System.DirectoryServices.AuthenticationTypes AuthenticationType, 
      string DomainName) { 
       loginPath=LoginPath; 
       loginUsername=LoginUsername; 
       loginPassword=LoginPassword; 
       authenticationType=AuthenticationType; 
       if(DomainName=="" || DomainName==null) 
      DomainName=System.Environment.UserDomainName; 
       domainName=DomainName; 
       Connect(); 
       } 
       #endregion 
       
       
       
       
      图1.4 构造器 
      这里的第一个构造器是一个基本的缺省构造器,能够在无需任何参数的情况下创建对象。这意味着该对象将在没有指定的安全权限的情况下连接到本机的WinNT提供者。 
       
      第二个构造器使我们能够指定连接到给定域的AD上所需要的证书,在需要使用给定的证书连接到任意域名时,这一构造器非常方便。 
       
      第二个构造器中增添了LoginPath参数,这将使我们能够覆盖LoginPath,能够选择缺省提供商之外的其他服务提供者。 
       
      下面的代码被我称为“活动方法”,代码如下所示: 
       
      public DSHelper.DSUser LoadUser(string username) 
       
       
       
      这一方法用来接收用户名,并在当前的提供者中查找DirectoryEntry。如果没有找到,就简单地返回NULL。 
       
      public System.Boolean AddUserToGroup(string groupname, DSHelper.DSUser dsUser) 
       
       
       
      这一方法接收现有组的名字和定制的DSUser类的实例,并试图将用户添加到提供的组中。这也是第一个我们能看到impersonation的方法()。这一方法的核心是下面这行代码: 
       
      public System.Collections.ArrayList GetGroups() 
       
       
       
      我们将使用该方法获得域中所有组的名单。 
       
      public System.Boolean DeleteUser(DSHelper.DSUser dsUser) 
       
       
       
      这一方法获得给定的用户名,并从活动目录中完全删除它。 
       
      public System.DirectoryServices.DirectoryEntry SaveUser(DSHelper.DSUser dsUser) 
       
       
       
      没有实际的在数据库中保存和插入记录的能力,就不能被称为一个完整的DAL。上面的方法可以完成这二项任务,它首先检查AD,看是否有指定的用户存在。如果存在,,则会用我们提供的数据更新该用户。如果用户不存在,就会创建一个用户。 
       
      public System.Boolean Connect() 
       
       
       
      最后,我们需要一个方法,与数据库进行连接,Connect()就是用来完成这一任务的方法。需要指出的是,此时,它不执行任何假冒的操作或指定使用AD的证书,我们只在需要的时候才提供证书,这就使得在没有提供安全证书的情况下,DAL只能在只读的状态下使用。 
       
      下面我们将上面的内容串起来,来看看我们如何使用DAL创建ASP.NET用户管理页。 
       
       
      ASP.NET用户管理页 
       
       
      在这一例子工程中,我们能够为系统管理员用户输入用户名和口令,它还提供了一个文本框,我们可以输入域中任何用户的名字,就会列出其所有属性。我们还可以对用户进行编辑、保存操作,也可以完全删除该用户。 
       
      现在我们来详细地回顾整个工程,其中重点是与DAL进行交互的部份。请读者考虑使用新的方法改进界面,并实际地创建一个可用性更高以及更友好的设计。另外,读者也可以考虑如何使用控制台应用程序创建界面。 
       
      扮演 
       
      “扮演”这个词的意思是,我们以其他人或用户的身份执行操作。在我们的ASP.NET应用程序中,这意味着我们可以暂时地客串其他用户,而不是IIS用来处理匿名访问的缺省帐户的ASP.NET用户。我们希望能够使自己的代码扮演对AD资源有更大访问权限的其他用户,以便对资源进行适当的修改。要完成这一过程非常简单。 
      

  2.   

    #region setup impersonation via interop 
       //需要保存详细资料时,为完成扮演需要通过InteropServices从COM中导入 
       public const int LOGON32_LOGON_INTERACTIVE = 2; 
       public const int LOGON32_PROVIDER_DEFAULT = 0; 
       System.Security.Principal.WindowsImpersonationContext impersonationContext; 
      [DllImport("advapi32.dll", CharSet=CharSet.Auto)]public static extern int 
      LogonUser(String lpszUserName, 
      String lpszDomain,String lpszPassword,int dwLogonType,int dwLogonProvider, 
      ref IntPtr phToken); 
      [DllImport("advapi32.dll", CharSet=System.Runtime.InteropServices.CharSet.Auto, 
      SetLastError=true)]public 
      extern static int DuplicateToken(IntPtr hToken, int impersonationLevel, 
      ref IntPtr hNewToken); 
       #endregion 
       
       
       
       
      图1.5 建立扮演 
       
       
      首先,我们需要从advapi32.dll中导入新的方法,其中包括一些有用的常量。名字为impersonationContext的变量将用来保持扮演操作之前的Windows用户。 
       
      这样,我们就建立了扮演,下面是一个如何使用它的例子: 
       
      if(impersonateValidUser(this.LoginUsername, this.DomainName, 
      this.loginPassword)) { 
       //在这里插入在指定用户的安全环境下运行的代码 
       //不要忘记取消扮演 
       undoImpersonation(); 
      } else { 
       //扮演操作失败了,插入保证失败后系统安全的机制 
      } 
       
       
       
       
      图1.6 扮演的使用 
       
       
      我们只需要简单地以有效的用户名和口令调用impersonateValidUser方法,来扮演该用户。从现在开始,只到调用undoImpersonation()之后,我们将以给定的用户名执行所有的操作。 
       
      为了使ASP.NET下的扮演操作能够正常地工作,我们应当改变machine.config(c:\winnt\microsoft.net\framework\v%VERSION%\config\machine.config)中的processModel节点,其中的username属性必须被设置成System。 
      

  3.   

    http://blog.joycode.com/liuhuimiao/posts/20946.aspx
      

  4.   

    我对AD结构不太了解,有谁能大概介绍一下用程序操作一个AD所要步骤,
    有这方面经历的朋友出来讲讲
      

  5.   

    我写了一段添加用户的代码如下,但报错为:
    -------
    未处理的“System.Runtime.InteropServices.COMException”类型的异常出现在 system.directoryservices.dll 中
    其他信息:该服务器不愿意处理该请求。
    -------
    string ADPath = "LDAP://test.com/CN=Users,DC=test,DC=com";
    string ADUser = "Administrator";
    string ADPassword = "test";
    DirectoryEntry entry = new DirectoryEntry(ADPath,ADUser,ADPassword,AuthenticationTypes.Secure);
    DirectoryEntry deUser = entry.Children.Add("CN=testUser", "user");
    entry.Properties["sAMAccountName"].Value = "testUser";
    entry.CommitChanges();
    entry.Close();
      

  6.   

    你的 test.com 是否可以ping 通 ?  登陆的用户是否具有权限 ? 进一步检查
      

  7.   

    to redbb
    test.com当然可能ping通,我直接在AD所在机器运行该程序也报同样错误!!
      

  8.   

    wait, I will check its answer
      

  9.   

    问题由wh_blackbird(wanmin) 搞定,给分