您的位置:首页 > 编程语言 > C#

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

2013-11-21 16:35 309 查看
今天用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;
}


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

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

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.DirectoryServices;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Litb.HRExtension
{
//静态AD连接类
public static class AdHerlp
{
#region 创建AD连接
/// <summary>
/// 创建AD连接
/// </summary>
/// <returns></returns>
public static DirectoryEntry GetDirectoryEntry()
{
DirectoryEntry de = new DirectoryEntry();
de.Path = "LDAP://testhr.com/CN=Users,DC=testhr,DC=com";
de.Username = @"administrator";
de.Password = "litb20!!";
return de;
}
#endregion

#region 获取目录实体集合(DomainReference传空即可)
/// <summary>
///
/// </summary>
/// <param name="DomainReference"></param>
/// <returns></returns>
public static DirectoryEntry GetDirectoryEntry(string DomainReference)
{
DirectoryEntry entry = new DirectoryEntry("LDAP://testhr.com" + DomainReference, "administrator", "litb20!!", AuthenticationTypes.Secure);
return entry;
}
#endregion
}

//AD操作类
public class ADHelper
{
/// <summary>
/// 判断用户是否存在
/// </summary>
/// <param name="UserName"></param>
/// <returns></returns>
public bool UserExists(string UserName)
{
DirectoryEntry de = AdHerlp.GetDirectoryEntry();
DirectorySearcher deSearch = new DirectorySearcher();
deSearch.SearchRoot = de;
deSearch.Filter = "(&(objectClass=user) (cn=" + UserName + "))";
SearchResultCollection results = deSearch.FindAll();
if (results.Count == 0)
{
return false;
}
else
{
return true;
}
}

/// <summary>
/// 创建一个新用户
/// </summary>
/// <param name="employeeID"></param>
/// <param name="name"></param>
/// <param name="login"></param>
/// <param name="email"></param>
/// <param name="group"></param>
public void CreateNewUser(string employeeID, string name, string login, string email, string group)
{
DirectoryEntry de = AdHerlp.GetDirectoryEntry();

/// 1. Create user account
DirectoryEntries users = de.Children;
DirectoryEntry newuser = users.Add("CN=" + login, "user");

/// 2. Set properties
SetProperty(newuser, "employeeID", employeeID);
SetProperty(newuser, "givenname", name);
SetProperty(newuser, "SAMAccountName", login);
SetProperty(newuser, "userPrincipalName", login);
SetProperty(newuser, "mail", email);
SetProperty(newuser, "Description", "Create User By HrESS System");
newuser.CommitChanges();

/// 3. Set password
newuser.AuthenticationType = AuthenticationTypes.Secure;
object[] password = new object[] { SetSecurePassword() };
object ret = newuser.Invoke("SetPassword", password);
newuser.CommitChanges();

//SetPassword(newuser);
//newuser.CommitChanges();

/// 4. Enable account
EnableAccount(newuser);

/// 5. Add user account to groups
AddUserToGroup(de, newuser, group);

/// 6. Create a mailbox in Microsoft Exchange
//GenerateMailBox(login);

newuser.Close();
de.Close();
}

/// <summary>
/// 修改用户属性
/// </summary>
/// <param name="de"></param>
/// <param name="PropertyName"></param>
/// <param name="PropertyValue"></param>
public static void SetProperty(DirectoryEntry de, string PropertyName, string PropertyValue)
{
if (PropertyValue != null)
{
if (de.Properties.Contains(PropertyName))
{
de.Properties[PropertyName][0] = PropertyValue;
}
else
{
de.Properties[PropertyName].Add(PropertyValue);
}
}
}

/// <summary>
/// 生成随机密码
/// </summary>
/// <returns></returns>
public string SetSecurePassword()
{
return "qwe123!@#";
}

/// <summary>
/// 设置用户新密码
/// </summary>
/// <param name="path"></param>
public void SetPassword(DirectoryEntry newuser)
{
newuser.AuthenticationType = AuthenticationTypes.Secure;
object[] password = new object[] { SetSecurePassword() };
object ret = newuser.Invoke("SetPassword", password);
newuser.CommitChanges();
newuser.Close();
}

/// <summary>
/// 启用用户帐号
/// </summary>
/// <param name="de"></param>
private static void EnableAccount(DirectoryEntry de)
{
//UF_DONT_EXPIRE_PASSWD 0x10000
int exp = (int)de.Properties["userAccountControl"].Value;
de.Properties["userAccountControl"].Value = exp | 0x0001;
de.CommitChanges();
//UF_ACCOUNTDISABLE 0x0002
int val = (int)de.Properties["userAccountControl"].Value;
de.Properties["userAccountControl"].Value = val & ~0x0002;
de.CommitChanges();
}

/// <summary>
/// 添加用户到组
/// </summary>
/// <param name="de"></param>
/// <param name="deUser"></param>
/// <param name="GroupName"></param>
public static void AddUserToGroup(DirectoryEntry de, DirectoryEntry deUser, string GroupName)
{
DirectorySearcher deSearch = new DirectorySearcher();
deSearch.SearchRoot = de;
deSearch.Filter = "(&(objectClass=group) (cn=" + GroupName + "))";
SearchResultCollection results = deSearch.FindAll();

bool isGroupMember = false;

if (results.Count > 0)
{
DirectoryEntry group = AdHerlp.GetDirectoryEntry(results[0].Path);

object members = group.Invoke("Members", null);
foreach (object member in (IEnumerable)members)
{
DirectoryEntry x = new DirectoryEntry(member);
if (x.Name != deUser.Name)
{
isGroupMember = false;
}
else
{
isGroupMember = true;
break;
}
}

if (!isGroupMember)
{
group.Invoke("Add", new object[] { deUser.Path.ToString() });
}
group.Close();
}
return;
}

/// <summary>
/// 禁用一个帐号
/// </summary>
/// <param name="EmployeeID"></param>
public void DisableAccount(string EmployeeID)
{
DirectoryEntry de = AdHerlp.GetDirectoryEntry();
DirectorySearcher ds = new DirectorySearcher(de);
ds.Filter = "(&(objectCategory=Person)(objectClass=user)(employeeID=" + EmployeeID + "))";
ds.SearchScope = SearchScope.Subtree;
SearchResult results = ds.FindOne();

if (results != null)
{
DirectoryEntry dey = AdHerlp.GetDirectoryEntry(results.Path);
int val = (int)dey.Properties["userAccountControl"].Value;
dey.Properties["userAccountControl"].Value = val | 0x0002;
dey.Properties["msExchHideFromAddressLists"].Value = "TRUE";
dey.CommitChanges();
dey.Close();
}

de.Close();
}

/// <summary>
/// 修改用户信息
/// </summary>
/// <param name="employeeID"></param>
/// <param name="department"></param>
/// <param name="title"></param>
/// <param name="company"></param>
public void ModifyUser(string employeeID, string department, string title, string company)
{
DirectoryEntry de = AdHerlp.GetDirectoryEntry();
DirectorySearcher ds = new DirectorySearcher(de);
ds.Filter = "(&(objectCategory=Person)(objectClass=user)(employeeID=" + employeeID + "))";
ds.SearchScope = SearchScope.Subtree;
SearchResult results = ds.FindOne();

if (results != null)
{
DirectoryEntry dey = AdHerlp.GetDirectoryEntry(results.Path);
SetProperty(dey, "department", department);
SetProperty(dey, "title", title);
SetProperty(dey, "company", company);
dey.CommitChanges();
dey.Close();
}

de.Close();
}

/// <summary>
/// 检验Email格式是否正确
/// </summary>
/// <param name="mail"></param>
/// <returns></returns>
public bool IsEmail(string mail)
{
Regex mailPattern = new Regex(@"\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*");
return mailPattern.IsMatch(mail);
}

/// <summary>
/// 搜索被修改过的用户
/// </summary>
/// <param name="fromdate"></param>
/// <returns></returns>
public DataTable GetModifiedUsers(DateTime fromdate)
{
DataTable dt = new DataTable();
dt.Columns.Add("EmployeeID");
dt.Columns.Add("Name");
dt.Columns.Add("Email");

DirectoryEntry de = AdHerlp.GetDirectoryEntry();
DirectorySearcher ds = new DirectorySearcher(de);

StringBuilder filter = new StringBuilder();
filter.Append("(&(objectCategory=Person)(objectClass=user)(whenChanged>=");
filter.Append(ToADDateString(fromdate));
filter.Append("))");

ds.Filter = filter.ToString();
ds.SearchScope = SearchScope.Subtree;
SearchResultCollection results = ds.FindAll();

foreach (SearchResult result in results)
{
DataRow dr = dt.NewRow();
DirectoryEntry dey = AdHerlp.GetDirectoryEntry(result.Path);
dr["EmployeeID"] = dey.Properties["employeeID"].Value;
dr["Name"] = dey.Properties["givenname"].Value;
dr["Email"] = dey.Properties["mail"].Value;
dt.Rows.Add(dr);
dey.Close();
}

de.Close();
return dt;
}

/// <summary>
/// 格式化AD的时间
/// </summary>
/// <param name="date"></param>
/// <returns></returns>
public string ToADDateString(DateTime date)
{
string year = date.Year.ToString();
int month = date.Month;
int day = date.Day;

StringBuilder sb = new StringBuilder();
sb.Append(year);
if (month < 10)
{
sb.Append("0");
}
sb.Append(month.ToString());
if (day < 10)
{
sb.Append("0");
}
sb.Append(day.ToString());
sb.Append("000000.0Z");
return sb.ToString();
}
}
}


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:\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,而这台机器没有对litb-inc.com的解析。

最终修改了DNS配置,问题解决。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: