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

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

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

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


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

        public static bool TryAuthenticate(string userName, string password)
        {
            string domain = "lixxx.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 = "xxxx";
            return de;

            DirectoryEntry entry = new DirectoryEntry("LDAP://testhr.com", "administrator", "xxxx", 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:\code\HrExtension\Litb.HRExtension\Litb.HRExtension\ADHelper.cs:行号 87   
在 ConsoleTest.Program.Main(String[] args) 位置 f:\code\HrExtension\Litb.HRExtension\ConsoleTest\Program.cs:行号 42

 

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

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

posted @ 2013-11-21 16:35  旋转木马的IT小窝  阅读(1801)  评论(0编辑  收藏  举报

回到顶部