• C# LDAP 管理(创建新用户)


    今天用C#实现了一套LDAP域账号的创建和查询,感受挺多。

    算是第一次接触LDAP吧,之前曾经做了一个登录的验证,就是查询功能,那个相对比较简单,用到了一个方法就搞定了。

    这次的需求是要用编程的方式创建域账号,实现域登陆。


    首先回顾一下之前查询用到的代码:

            public static bool TryAuthenticate(string userName, string password)
            {
                string domain = "litb-inc.com";
                bool isLogin = false;
                try
                {
                    DirectoryEntry entry = new DirectoryEntry(string.Format("LDAP://{0}", domain), userName, password);
                    entry.RefreshCache();
                    DBLog.Debug("check success");
                    isLogin = true;
                }
                catch (Exception ex)
                {
                    DBLog.Debug("域验证抛出异常 :" + ex.Message + ex.InnerException);
                    isLogin = false;
                }
                return isLogin;
            }

    这是验证指定用户是否在域里认证通过。


    接下来,实现创建域账户的操作。在网上找到了一个操作类:

      1 using System;
      2 using System.Collections;
      3 using System.Collections.Generic;
      4 using System.Data;
      5 using System.DirectoryServices;
      6 using System.Linq;
      7 using System.Text;
      8 using System.Text.RegularExpressions;
      9 
     10 namespace Litb.HRExtension
     11 {
     12     //静态AD连接类
     13     public static class AdHerlp
     14     {
     15         #region 创建AD连接
     16         /// <summary>
     17         /// 创建AD连接
     18         /// </summary>
     19         /// <returns></returns>
     20         public static DirectoryEntry GetDirectoryEntry()
     21         {
     22             DirectoryEntry de = new DirectoryEntry();
     23             de.Path = "LDAP://testhr.com/CN=Users,DC=testhr,DC=com";
     24             de.Username = @"administrator";
     25             de.Password = "litb20!!";
     26             return de;
     27         }
     28         #endregion
     29 
     30         #region 获取目录实体集合(DomainReference传空即可)
     31         /// <summary>
     32         ///
     33         /// </summary>
     34         /// <param name="DomainReference"></param>
     35         /// <returns></returns>
     36         public static DirectoryEntry GetDirectoryEntry(string DomainReference)
     37         {
     38             DirectoryEntry entry = new DirectoryEntry("LDAP://testhr.com" + DomainReference, "administrator", "litb20!!", AuthenticationTypes.Secure);
     39             return entry;
     40         }
     41         #endregion
     42     }
     43 
     44     //AD操作类
     45     public class ADHelper
     46     {
     47         /// <summary>
     48         /// 判断用户是否存在
     49         /// </summary>
     50         /// <param name="UserName"></param>
     51         /// <returns></returns>
     52         public bool UserExists(string UserName)
     53         {
     54             DirectoryEntry de = AdHerlp.GetDirectoryEntry();
     55             DirectorySearcher deSearch = new DirectorySearcher();
     56             deSearch.SearchRoot = de;
     57             deSearch.Filter = "(&(objectClass=user) (cn=" + UserName + "))";
     58             SearchResultCollection results = deSearch.FindAll();
     59             if (results.Count == 0)
     60             {
     61                 return false;
     62             }
     63             else
     64             {
     65                 return true;
     66             }
     67         }
     68 
     69         /// <summary>
     70         /// 创建一个新用户
     71         /// </summary>
     72         /// <param name="employeeID"></param>
     73         /// <param name="name"></param>
     74         /// <param name="login"></param>
     75         /// <param name="email"></param>
     76         /// <param name="group"></param>
     77         public void CreateNewUser(string employeeID, string name, string login, string email, string group)
     78         {
     79             DirectoryEntry de = AdHerlp.GetDirectoryEntry();
     80 
     81             /// 1. Create user account
     82             DirectoryEntries users = de.Children;
     83             DirectoryEntry newuser = users.Add("CN=" + login, "user");
     84 
     85             /// 2. Set properties
     86             SetProperty(newuser, "employeeID", employeeID);
     87             SetProperty(newuser, "givenname", name);
     88             SetProperty(newuser, "SAMAccountName", login);
     89             SetProperty(newuser, "userPrincipalName", login);
     90             SetProperty(newuser, "mail", email);
     91             SetProperty(newuser, "Description", "Create User By HrESS System");
     92             newuser.CommitChanges();
     93 
     94             /// 3. Set password
     95             newuser.AuthenticationType = AuthenticationTypes.Secure;
     96             object[] password = new object[] { SetSecurePassword() };
     97             object ret = newuser.Invoke("SetPassword", password);
     98             newuser.CommitChanges();
     99 
    100             //SetPassword(newuser);
    101             //newuser.CommitChanges();
    102 
    103             /// 4. Enable account           
    104             EnableAccount(newuser);
    105 
    106             /// 5. Add user account to groups
    107             AddUserToGroup(de, newuser, group);
    108 
    109             /// 6. Create a mailbox in Microsoft Exchange   
    110             //GenerateMailBox(login);
    111 
    112             newuser.Close();
    113             de.Close();
    114         }
    115 
    116         /// <summary>
    117         /// 修改用户属性
    118         /// </summary>
    119         /// <param name="de"></param>
    120         /// <param name="PropertyName"></param>
    121         /// <param name="PropertyValue"></param>
    122         public static void SetProperty(DirectoryEntry de, string PropertyName, string PropertyValue)
    123         {
    124             if (PropertyValue != null)
    125             {
    126                 if (de.Properties.Contains(PropertyName))
    127                 {
    128                     de.Properties[PropertyName][0] = PropertyValue;
    129                 }
    130                 else
    131                 {
    132                     de.Properties[PropertyName].Add(PropertyValue);
    133                 }
    134             }
    135         }
    136 
    137         /// <summary>
    138         /// 生成随机密码
    139         /// </summary>
    140         /// <returns></returns>
    141         public string SetSecurePassword()
    142         {
    143             return "qwe123!@#";
    144         }
    145 
    146         /// <summary>
    147         /// 设置用户新密码
    148         /// </summary>
    149         /// <param name="path"></param>
    150         public void SetPassword(DirectoryEntry newuser)
    151         {
    152             newuser.AuthenticationType = AuthenticationTypes.Secure;
    153             object[] password = new object[] { SetSecurePassword() };
    154             object ret = newuser.Invoke("SetPassword", password);
    155             newuser.CommitChanges();
    156             newuser.Close();
    157         }
    158 
    159         /// <summary>
    160         /// 启用用户帐号
    161         /// </summary>
    162         /// <param name="de"></param>
    163         private static void EnableAccount(DirectoryEntry de)
    164         {
    165             //UF_DONT_EXPIRE_PASSWD 0x10000
    166             int exp = (int)de.Properties["userAccountControl"].Value;
    167             de.Properties["userAccountControl"].Value = exp | 0x0001;
    168             de.CommitChanges();
    169             //UF_ACCOUNTDISABLE 0x0002
    170             int val = (int)de.Properties["userAccountControl"].Value;
    171             de.Properties["userAccountControl"].Value = val & ~0x0002;
    172             de.CommitChanges();
    173         }
    174 
    175         /// <summary>
    176         /// 添加用户到组
    177         /// </summary>
    178         /// <param name="de"></param>
    179         /// <param name="deUser"></param>
    180         /// <param name="GroupName"></param>
    181         public static void AddUserToGroup(DirectoryEntry de, DirectoryEntry deUser, string GroupName)
    182         {
    183             DirectorySearcher deSearch = new DirectorySearcher();
    184             deSearch.SearchRoot = de;
    185             deSearch.Filter = "(&(objectClass=group) (cn=" + GroupName + "))";
    186             SearchResultCollection results = deSearch.FindAll();
    187 
    188             bool isGroupMember = false;
    189 
    190             if (results.Count > 0)
    191             {
    192                 DirectoryEntry group = AdHerlp.GetDirectoryEntry(results[0].Path);
    193 
    194                 object members = group.Invoke("Members", null);
    195                 foreach (object member in (IEnumerable)members)
    196                 {
    197                     DirectoryEntry x = new DirectoryEntry(member);
    198                     if (x.Name != deUser.Name)
    199                     {
    200                         isGroupMember = false;
    201                     }
    202                     else
    203                     {
    204                         isGroupMember = true;
    205                         break;
    206                     }
    207                 }
    208 
    209                 if (!isGroupMember)
    210                 {
    211                     group.Invoke("Add", new object[] { deUser.Path.ToString() });
    212                 }
    213                 group.Close();
    214             }
    215             return;
    216         }
    217 
    218         /// <summary>
    219         /// 禁用一个帐号
    220         /// </summary>
    221         /// <param name="EmployeeID"></param>
    222         public void DisableAccount(string EmployeeID)
    223         {
    224             DirectoryEntry de = AdHerlp.GetDirectoryEntry();
    225             DirectorySearcher ds = new DirectorySearcher(de);
    226             ds.Filter = "(&(objectCategory=Person)(objectClass=user)(employeeID=" + EmployeeID + "))";
    227             ds.SearchScope = SearchScope.Subtree;
    228             SearchResult results = ds.FindOne();
    229 
    230             if (results != null)
    231             {
    232                 DirectoryEntry dey = AdHerlp.GetDirectoryEntry(results.Path);
    233                 int val = (int)dey.Properties["userAccountControl"].Value;
    234                 dey.Properties["userAccountControl"].Value = val | 0x0002;
    235                 dey.Properties["msExchHideFromAddressLists"].Value = "TRUE";
    236                 dey.CommitChanges();
    237                 dey.Close();
    238             }
    239 
    240             de.Close();
    241         }
    242 
    243         /// <summary>
    244         /// 修改用户信息
    245         /// </summary>
    246         /// <param name="employeeID"></param>
    247         /// <param name="department"></param>
    248         /// <param name="title"></param>
    249         /// <param name="company"></param>
    250         public void ModifyUser(string employeeID, string department, string title, string company)
    251         {
    252             DirectoryEntry de = AdHerlp.GetDirectoryEntry();
    253             DirectorySearcher ds = new DirectorySearcher(de);
    254             ds.Filter = "(&(objectCategory=Person)(objectClass=user)(employeeID=" + employeeID + "))";
    255             ds.SearchScope = SearchScope.Subtree;
    256             SearchResult results = ds.FindOne();
    257 
    258             if (results != null)
    259             {
    260                 DirectoryEntry dey = AdHerlp.GetDirectoryEntry(results.Path);
    261                 SetProperty(dey, "department", department);
    262                 SetProperty(dey, "title", title);
    263                 SetProperty(dey, "company", company);
    264                 dey.CommitChanges();
    265                 dey.Close();
    266             }
    267 
    268             de.Close();
    269         }
    270 
    271         /// <summary>
    272         /// 检验Email格式是否正确
    273         /// </summary>
    274         /// <param name="mail"></param>
    275         /// <returns></returns>
    276         public bool IsEmail(string mail)
    277         {
    278             Regex mailPattern = new Regex(@"w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*");
    279             return mailPattern.IsMatch(mail);
    280         }
    281 
    282         /// <summary>
    283         /// 搜索被修改过的用户
    284         /// </summary>
    285         /// <param name="fromdate"></param>
    286         /// <returns></returns>
    287         public DataTable GetModifiedUsers(DateTime fromdate)
    288         {
    289             DataTable dt = new DataTable();
    290             dt.Columns.Add("EmployeeID");
    291             dt.Columns.Add("Name");
    292             dt.Columns.Add("Email");
    293 
    294             DirectoryEntry de = AdHerlp.GetDirectoryEntry();
    295             DirectorySearcher ds = new DirectorySearcher(de);
    296 
    297             StringBuilder filter = new StringBuilder();
    298             filter.Append("(&(objectCategory=Person)(objectClass=user)(whenChanged>=");
    299             filter.Append(ToADDateString(fromdate));
    300             filter.Append("))");
    301 
    302             ds.Filter = filter.ToString();
    303             ds.SearchScope = SearchScope.Subtree;
    304             SearchResultCollection results = ds.FindAll();
    305 
    306             foreach (SearchResult result in results)
    307             {
    308                 DataRow dr = dt.NewRow();
    309                 DirectoryEntry dey = AdHerlp.GetDirectoryEntry(result.Path);
    310                 dr["EmployeeID"] = dey.Properties["employeeID"].Value;
    311                 dr["Name"] = dey.Properties["givenname"].Value;
    312                 dr["Email"] = dey.Properties["mail"].Value;
    313                 dt.Rows.Add(dr);
    314                 dey.Close();
    315             }
    316 
    317             de.Close();
    318             return dt;
    319         }
    320 
    321         /// <summary>
    322         /// 格式化AD的时间
    323         /// </summary>
    324         /// <param name="date"></param>
    325         /// <returns></returns>
    326         public string ToADDateString(DateTime date)
    327         {
    328             string year = date.Year.ToString();
    329             int month = date.Month;
    330             int day = date.Day;
    331 
    332             StringBuilder sb = new StringBuilder();
    333             sb.Append(year);
    334             if (month < 10)
    335             {
    336                 sb.Append("0");
    337             }
    338             sb.Append(month.ToString());
    339             if (day < 10)
    340             {
    341                 sb.Append("0");
    342             }
    343             sb.Append(day.ToString());
    344             sb.Append("000000.0Z");
    345             return sb.ToString();
    346         }
    347     }
    348 }
    View Code

    有了这个操作类,就可以进行域账号的创建了,调用示例:

    Console.WriteLine("Begin CreateNewUser");
    string name = "wj" + System.Guid.NewGuid().ToString().Substring(0, 5);
    string id = System.Guid.NewGuid().ToString().Substring(0, 5);my.CreateNewUser(id, name, name, name + "@testhr.com", "testhr.com/Users");
    Console.WriteLine("域用户名创建成功:" + name);

    注意域账号的用户名不能有类似-,下划线之类的特殊字符。


    在最初尝试的时候,创建对象 DirectoryEntry的时候总是有问题,最终这两种方式都是有效的:

                DirectoryEntry de = new DirectoryEntry();
                de.Path = "LDAP://testhr.com/CN=Users,DC=testhr,DC=com";
                de.Username = @"administrator";
                de.Password = "litb20!!";
                return de;

                DirectoryEntry entry = new DirectoryEntry("LDAP://testhr.com", "administrator", "litb20!!", AuthenticationTypes.Secure);
                return entry;


    其次,在创建完用户以后,需要设置用户的密码,这个方法总是报错,后来经过检查,发现如果只传递path字符串,是不行的,必须操作现有对象的Invoke方法才可以!

    或者传递对象引用。


    最终,成功创建了域账户。


    在测试的时候,同一台机器加入了多个账号后,就会有问题,报出类似这样的错误:

    最终,可以通过在服务器上删除这台电脑的方式来解决,或者重命名本地计算机名称。

     当程序放在服务器上时,又报了错误:

    Info:该服务器不可操作。     
    在 System.DirectoryServices.DirectoryEntry.Bind(Boolean throwIfFail)   
    在 System.DirectoryServices.DirectoryEntry.Bind()   
    在 System.DirectoryServices.DirectoryEntry.get_IsContainer()
    在 System.DirectoryServices.DirectoryEntries.CheckIsContainer()
    在 System.DirectoryServices.DirectoryEntries.Add(String name, String schemaClassName)
    在 Litb.HRExtension.ADHelper.CreateNewUser(String name, String password, String firstname, String lastname, String email, String group)
    位置 f:codeHrExtensionLitb.HRExtensionLitb.HRExtensionADHelper.cs:行号 87   
    在 ConsoleTest.Program.Main(String[] args) 位置 f:codeHrExtensionLitb.HRExtensionConsoleTestProgram.cs:行号 42

    最终找到的原因是服务器win2003的DNS设为了一个固定ip,而这台机器没有对litb-inc.com的解析。

    最终修改了DNS配置,问题解决。

  • 相关阅读:
    Android StickHeaderRecyclerView
    Android上使用RecyclerView实现顶部悬浮标题效果的Sticky Title View
    Android 使用RecyclerView优雅实现悬浮标题通讯录
    AS打包出现app:transformClassesAndResourcesWithProguardForRelease错误
    Dubbo架构原理
    Android 收藏夹之Android篇
    Android FlycoDialog 简单实用的自定义Android弹窗对话框之Dialog篇
    Kotlin 的23篇基础
    Kotlin编程之AndroidStudio(包括3.0与2.x版本)配置与使用
    Chrome 62 的大坑:修改密码后始终使用保存的旧密码登录团队
  • 原文地址:https://www.cnblogs.com/dannywang/p/3435840.html
Copyright © 2020-2023  润新知