public sealed class ADHelper { #region 属性 /// <summary> /// 扮演类实例 /// </summary> private static IdentityImpersonation impersonate = new IdentityImpersonation(ADUser, ADPassword, DomainName); /// <summary> /// AD域地址 /// </summary> public static string DomainName = "kxdigit.com"; /// <summary> /// LDAP绑定路径 /// </summary> public static string ADPath = "LDAP://testkxdigit.com"; /// <summary> /// 登录帐号 /// </summary> public static string ADUser = "Administrator"; /// <summary> /// 登录密码 /// </summary> public static string ADPassword = "admin@123"; #endregion #region 组织单位 /// <summary> /// 创建组织单位 /// </summary> /// <param name="ldapDN">DN 位置</param> /// <param name="orgName">组织单位名称</param> /// <returns></returns> public static DirectoryEntry CreateOU(string ldapDN, string orgName) { DirectoryEntry entry = GetDirectoryObject(); DirectoryEntry subEntry = entry.Children.Find(ldapDN); DirectoryEntry OU = subEntry.Children.Add("OU=" + orgName, "organizationalUnit"); OU.CommitChanges(); return OU; } /// <summary> /// 创建组织单位 /// </summary> /// <param name="entry">上级单位</param> /// <param name="orgName">组织单位名称</param> /// <returns></returns> public static DirectoryEntry CreateOU(DirectoryEntry entry, string orgName) { DirectoryEntry OU = entry.Children.Add("OU=" + orgName, "organizationalUnit"); OU.CommitChanges(); return OU; } /// <summary> /// 判断是否存在组织单位OU /// </summary> /// <param name="entry"></param> /// <param name="ouName"></param> /// <returns></returns> public static DirectoryEntry IsExistOU(DirectoryEntry entry, string ouName) { DirectoryEntry ou = new DirectoryEntry(); try { ou = entry.Children.Find("OU=" + ouName); return ou; } catch { return null; } } #endregion #region 组 /// <summary> /// 创建组 /// </summary> /// <param name="ldapDN">DN 位置</param> /// <param name="groupName">组名</param> /// <returns></returns> public static DirectoryEntry CreateGroup(string ldapDN, string groupName) { DirectoryEntry entry = GetDirectoryObject(); DirectoryEntry subEntry = entry.Children.Find(ldapDN); DirectoryEntry OU = subEntry.Children.Add("OU=" + groupName, "group"); OU.CommitChanges(); return OU; } /// <summary> /// 创建组 /// </summary> /// <param name="entry">上级单位</param> /// <param name="groupName">组名</param> /// <returns></returns> public static DirectoryEntry CreateGroup(DirectoryEntry entry, string groupName) { DirectoryEntry OU = entry.Children.Add("OU=" + groupName, "group"); OU.CommitChanges(); return OU; } /// <summary> /// 将指定的用户添加到指定的组中。默认为 Users 下的组和用户。 /// </summary> /// <param name="userCommonName">用户公共名称</param> /// <param name="groupName">组名</param> public static void AddUserToGroup(string userCommonName, string groupName) { DirectoryEntry oGroup = GetDirectoryEntryOfGroup(groupName); DirectoryEntry oUser = GetDirectoryEntry(userCommonName); impersonate.BeginImpersonate(); oGroup.Properties["member"].Add(oUser.Properties["distinguishedName"].Value); oGroup.CommitChanges(); impersonate.StopImpersonate(); oGroup.Close(); oUser.Close(); } /// <summary> /// 根据组名取得用户组的 对象 /// </summary> /// <param name="groupName">组名</param> /// <returns></returns> public static DirectoryEntry GetDirectoryEntryOfGroup(string groupName) { DirectoryEntry de = GetDirectoryObject(); DirectorySearcher deSearch = new DirectorySearcher(de); deSearch.Filter = "(&(objectClass=group)(cn=" + groupName + "))"; deSearch.SearchScope = SearchScope.Subtree; try { SearchResult result = deSearch.FindOne(); de = new DirectoryEntry(result.Path); return de; } catch { return null; } } /// <summary> /// 将用户从指定组中移除。默认为 Users 下的组和用户。 /// </summary> /// <param name="userCommonName">用户公共名称</param> /// <param name="groupName">组名</param> public static void RemoveUserFromGroup(string userCommonName, string groupName) { DirectoryEntry oGroup = GetDirectoryEntryOfGroup(groupName); DirectoryEntry oUser = GetDirectoryEntry(userCommonName); impersonate.BeginImpersonate(); oGroup.Properties["member"].Remove(oUser.Properties["distinguishedName"].Value); oGroup.CommitChanges(); impersonate.StopImpersonate(); oGroup.Close(); oUser.Close(); } #endregion #region 用户 /// <summary> /// 创建用户 /// </summary> /// <param name="users"></param> public static void CreateNewUser(List<ADUser> users) { DirectoryEntry entry = GetDirectoryObject(); DirectoryEntry subEntry = new DirectoryEntry(); DirectoryEntry tempEntry = new DirectoryEntry(); foreach (var user in users) { if (user.Level == 1) { if (user.IsOU) { tempEntry = IsExistOU(entry, user.Department); if (tempEntry == null) { subEntry = CreateOU(entry, user.Department); } else { subEntry = tempEntry; } } else { tempEntry = IsExistOU(entry, user.Department); if (tempEntry == null) { subEntry = CreateGroup(entry, user.Department); } else { subEntry = tempEntry; } } } else { if (user.IsOU) { tempEntry = IsExistOU(subEntry, user.Department); if (tempEntry == null) { subEntry = CreateOU(subEntry, user.Department); } else { subEntry = tempEntry; } } else { tempEntry = IsExistOU(subEntry, user.Department); if (tempEntry == null) { subEntry = CreateGroup(subEntry, user.Department); } else { subEntry = tempEntry; } } } if (!string.IsNullOrEmpty(user.UserName)) { CreateNewUser(subEntry, user.UserName, user.LoginName, user.Password); } } } /// <summary> /// 指定单位下创建用户 /// </summary> /// <param name="entry"></param> /// <param name="commonName"></param> /// <param name="sAMAccountName"></param> /// <param name="password"></param> /// <returns></returns> public static DirectoryEntry CreateNewUser(DirectoryEntry entry, string commonName, string sAMAccountName, string password) { DirectoryEntry deUser = entry.Children.Add("CN=" + commonName, "user"); // 用户登录名 deUser.Properties["userPrincipalName"].Value = sAMAccountName + "@" + DomainName; // 用户登录名(Windows 2000 之前版本) deUser.Properties["sAMAccountName"].Value = sAMAccountName; deUser.CommitChanges(); deUser.AuthenticationType = AuthenticationTypes.Secure; object[] PSD = new object[] { password }; object ret = deUser.Invoke("SetPassword", PSD); ADHelper.EnableUser(commonName); deUser.Close(); return deUser; } /// <summary> /// 删除指定用户 /// </summary> /// <param name="userName">用户名称</param> /// <returns></returns> public static bool DelUser(string userName) { try { //DomainName:填写域名, Administrator表示登录账户,123456密码。 PrincipalContext context = new PrincipalContext(ContextType.Domain, DomainName, ADUser, ADPassword); UserPrincipal user = UserPrincipal.FindByIdentity(context, userName); if (user != null) { user.Delete(); } return true; } catch { return false; } } /// <summary> /// 判断指定公共名称的用户是否存在 /// </summary> /// <param name="commonName">用户公共名称</param> /// <returns>如果存在,返回 true;否则返回 false</returns> public static bool IsUserExists(string commonName) { DirectoryEntry de = GetDirectoryObject(); DirectorySearcher deSearch = new DirectorySearcher(de); deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(cn=" + commonName + "))"; // LDAP 查询串 SearchResultCollection results = deSearch.FindAll(); if (results.Count == 0) return false; else return true; } /// <summary> /// 判断用户帐号是否激活 /// </summary> /// <param name="userAccountControl">用户帐号属性控制器</param> /// <returns>如果用户帐号已经激活,返回 true;否则返回 false</returns> public static bool IsAccountActive(int userAccountControl) { int userAccountControl_Disabled = Convert.ToInt32(ADS_USER_FLAG_ENUM.ADS_UF_ACCOUNTDISABLE); int flagExists = userAccountControl & userAccountControl_Disabled; if (flagExists > 0) return false; else return true; } /// <summary> /// 设置用户密码,管理员可以通过它来修改指定用户的密码。 /// </summary> /// <param name="commonName">用户公共名称</param> /// <param name="newPassword">用户新密码</param> public static void SetPassword(string commonName, string newPassword) { DirectoryEntry de = GetDirectoryObject(commonName); // 模拟超级管理员,以达到有权限修改用户密码 impersonate.BeginImpersonate(); de.Invoke("SetPassword", new object[] { newPassword }); impersonate.StopImpersonate(); de.Close(); } public void SetPassword(DirectoryEntry newuser, string pwd) { newuser.AuthenticationType = AuthenticationTypes.Secure; object[] password = new object[] { pwd }; object ret = newuser.Invoke("SetPassword", pwd); newuser.CommitChanges(); newuser.Close(); } public static string SetSecurePassword(string pwd) { return pwd; } /// <summary> /// 修改密码 /// </summary> /// <param name="UserName">用户名</param> /// <param name="strOldPassword">旧密码</param> /// <param name="strNewPassword">新密码</param> /// <returns></returns> public static bool ChangePassword(string UserName, string strOldPassword, string strNewPassword) { bool passwordChanged = false; DirectoryEntry oDE = GetUser(UserName); if (oDE != null) { oDE.Invoke("ChangePassword", new object[] { strOldPassword, strNewPassword }); passwordChanged = true; } return passwordChanged; } /// <summary> /// 修改用户密码 /// </summary> /// <param name="commonName">用户公共名称</param> /// <param name="oldPassword">旧密码</param> /// <param name="newPassword">新密码</param> public static void ChangeUserPassword(string commonName, string oldPassword, string newPassword) { // to-do: 需要解决密码策略问题 DirectoryEntry oUser = GetDirectoryEntry(commonName); oUser.Invoke("ChangePassword", new Object[] { oldPassword, newPassword }); oUser.Close(); } /// <summary> /// 启用指定公共名称的用户 /// </summary> /// <param name="commonName">用户公共名称</param> public static void EnableUser(string commonName) { try { //DomainName:填写域名, Administrator表示登录账户,123456密码。 PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, DomainName, ADUser, ADPassword); UserPrincipal userPrincipal = UserPrincipal.FindByIdentity (principalContext, commonName); userPrincipal.Enabled = true; //如果是禁用这里就改成false userPrincipal.Save(); } catch (Exception ex) { } } /// <summary> /// 禁用指定公共名称的用户 /// </summary> /// <param name="commonName">用户公共名称</param> public static void DisableUser(string commonName) { try { PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, DomainName, ADUser, ADPassword); UserPrincipal userPrincipal = UserPrincipal.FindByIdentity (principalContext, commonName); userPrincipal.Enabled = false; userPrincipal.Save(); } catch (Exception ex) { Console.WriteLine(ex.Message); } } /// <summary> /// 设置帐号密码,管理员可以通过它来修改指定帐号的密码。 /// </summary> /// <param name="sAMAccountName">用户帐号</param> /// <param name="newPassword">用户新密码</param> public static void SetPasswordByAccount(string sAMAccountName, string newPassword) { DirectoryEntry de = GetDirectoryEntryByAccount(sAMAccountName); // 模拟超级管理员,以达到有权限修改用户密码 IdentityImpersonation impersonate = new IdentityImpersonation(ADUser, ADPassword, DomainName); impersonate.BeginImpersonate(); de.Invoke("SetPassword", new object[] { newPassword }); impersonate.StopImpersonate(); de.Close(); } #endregion #region 查询 /// <summary> /// 根据指定用户名和密码获得相应DirectoryEntry实体 /// </summary> /// <param name="userName"></param> /// <param name="password"></param> /// <returns></returns> private static DirectoryEntry GetDirectoryObject(string userName, string password) { DirectoryEntry entry = new DirectoryEntry(ADPath, userName, password, AuthenticationTypes.None); return entry; } /// <summary> /// i.e. /CN=Users,DC=creditsights, DC=cyberelves, DC=Com /// </summary> /// <param name="domainReference"></param> /// <returns></returns> private static DirectoryEntry GetDirectoryObject(string domainReference) { DirectoryEntry entry = new DirectoryEntry(ADPath + domainReference, ADUser, ADPassword, AuthenticationTypes.Secure); return entry; } /// <summary> /// 获得以UserName,Password创建的DirectoryEntry /// </summary> /// <param name="domainReference"></param> /// <param name="userName"></param> /// <param name="password"></param> /// <returns></returns> private static DirectoryEntry GetDirectoryObject(string domainReference, string userName, string password) { DirectoryEntry entry = new DirectoryEntry(ADPath + domainReference, userName, password, AuthenticationTypes.Secure); return entry; } /// <summary> /// 获得DirectoryEntry对象实例,以管理员登陆AD /// </summary> /// <returns></returns> private static DirectoryEntry GetDirectoryObject() { DirectoryEntry entry = new DirectoryEntry(ADPath, ADUser, ADPassword, AuthenticationTypes.Secure); return entry; } /// <summary> /// 根据用户名找到用户对象 /// </summary> /// <param name="UserName"></param> /// <returns></returns> private static DirectoryEntry GetUser(string UserName) { DirectoryEntry de = GetDirectoryObject(); DirectorySearcher deSearch = new DirectorySearcher(); deSearch.SearchRoot = de; deSearch.Filter = "(&(objectClass=user)(SAMAccountName=" + UserName + "))"; deSearch.SearchScope = SearchScope.Subtree; SearchResult results = deSearch.FindOne(); if (!(results == null)) { // **THIS IS THE MOST IMPORTANT LINE** de = new DirectoryEntry(results.Path, "username", "password", AuthenticationTypes.Secure); return de; } else { return null; } } /// <summary> /// 根据用户帐号称取得用户的 对象 /// </summary> /// <param name="sAMAccountName">用户帐号名</param> /// <returns></returns> public static DirectoryEntry GetDirectoryEntryByAccount(string sAMAccountName) { DirectoryEntry de = GetDirectoryObject(); DirectorySearcher deSearch = new DirectorySearcher(de); deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(sAMAccountName=" + sAMAccountName + "))"; deSearch.SearchScope = SearchScope.Subtree; try { SearchResult result = deSearch.FindOne(); de = new DirectoryEntry(result.Path); return de; } catch { return null; } } /// <summary> /// 根据用户帐号和密码取得用户的 对象 /// </summary> /// <param name="sAMAccountName">用户帐号名</param> /// <param name="password">用户密码</param> /// <returns>如果找到该用户,则返回用户的 对象;否则返回 null</returns> public static DirectoryEntry GetDirectoryEntryByAccount(string sAMAccountName, string password) { DirectoryEntry de = GetDirectoryEntryByAccount(sAMAccountName); if (de != null) { string commonName = de.Properties["cn"][0].ToString(); if (GetDirectoryEntry(commonName, password) != null) return GetDirectoryEntry(commonName, password); else return null; } else { return null; } } /// <summary> /// 根据用户公共名称和密码取得用户的 对象。 /// </summary> /// <param name="commonName">用户公共名称</param> /// <param name="password">用户密码</param> /// <returns></returns> public static DirectoryEntry GetDirectoryEntry(string commonName, string password) { DirectoryEntry de = GetDirectoryObject(commonName, password); DirectorySearcher deSearch = new DirectorySearcher(de); deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(cn=" + commonName + "))"; deSearch.SearchScope = SearchScope.Subtree; try { SearchResult result = deSearch.FindOne(); de = new DirectoryEntry(result.Path); return de; } catch { return null; } } /// <summary> /// 根据用户公共名称取得用户的 对象 /// </summary> /// <param name="commonName">用户公共名称</param> /// <returns></returns> public static DirectoryEntry GetDirectoryEntry(string commonName) { DirectoryEntry de = GetDirectoryObject(); DirectorySearcher deSearch = new DirectorySearcher(de); deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(cn=" + commonName + "))"; deSearch.SearchScope = SearchScope.Subtree; try { SearchResult result = deSearch.FindOne(); de = new DirectoryEntry(result.Path); return de; } catch { return null; } } #endregion } public enum ADS_USER_FLAG_ENUM { /// <summary> /// 登录脚本标志。如果通过 ADSI LDAP 进行读或写操作时,该标志失效。如果通过 ADSI WINNT,该标志为只读 /// </summary> ADS_UF_SCRIPT = 0X0001, /// <summary> /// 用户帐号禁用标志 /// </summary> ADS_UF_ACCOUNTDISABLE = 0X0002, /// <summary> /// 主文件夹标志 /// </summary> ADS_UF_HOMEDIR_REQUIRED = 0X0008, /// <summary> /// 过期标志 /// </summary> ADS_UF_LOCKOUT = 0X0010, /// <summary> /// 用户密码不是必须的 /// </summary> ADS_UF_PASSWD_NOTREQD = 0X0020, /// <summary> /// 密码不能更改标志 /// </summary> ADS_UF_PASSWD_CANT_CHANGE = 0X0040, /// <summary> /// 使用可逆的加密保存密码 /// </summary> ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED = 0X0080, /// <summary> /// 本地帐号标志 /// </summary> ADS_UF_TEMP_DUPLICATE_ACCOUNT = 0X0100, /// <summary> /// 普通用户的默认帐号类型 /// </summary> ADS_UF_NORMAL_ACCOUNT = 0X0200, /// <summary> /// 跨域的信任帐号标志 /// </summary> ADS_UF_INTERDOMAIN_TRUST_ACCOUNT = 0X0800, /// <summary> /// 工作站信任帐号标志 /// </summary> ADS_UF_WORKSTATION_TRUST_ACCOUNT = 0x1000, /// <summary> /// 服务器信任帐号标志 /// </summary> ADS_UF_SERVER_TRUST_ACCOUNT = 0X2000, /// <summary> /// 密码永不过期标志 /// </summary> ADS_UF_DONT_EXPIRE_PASSWD = 0X10000, /// <summary> /// MNS 帐号标志 /// </summary> ADS_UF_MNS_LOGON_ACCOUNT = 0X20000, /// <summary> /// 交互式登录必须使用智能卡 /// </summary> ADS_UF_SMARTCARD_REQUIRED = 0X40000, /// <summary> /// 当设置该标志时,服务帐号(用户或计算机帐号)将通过 Kerberos 委托信任 /// </summary> ADS_UF_TRUSTED_FOR_DELEGATION = 0X80000, /// <summary> /// 当设置该标志时,即使服务帐号是通过 Kerberos 委托信任的,敏感帐号不能被委托 /// </summary> ADS_UF_NOT_DELEGATED = 0X100000, /// <summary> /// 此帐号需要 DES 加密类型 /// </summary> ADS_UF_USE_DES_KEY_ONLY = 0X200000, /// <summary> /// 不要进行 Kerberos 预身份验证 /// </summary> ADS_UF_DONT_REQUIRE_PREAUTH = 0X4000000, /// <summary> /// 用户密码过期标志 /// </summary> ADS_UF_PASSWORD_EXPIRED = 0X800000, /// <summary> /// 用户帐号可委托标志 /// </summary> ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0X1000000 } /// <summary> /// 用户模拟角色类。实现在程序段内进行用户角色模拟。 /// </summary> public class IdentityImpersonation { [DllImport("advapi32.dll", SetLastError = true)] public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public extern static bool CloseHandle(IntPtr handle); // 要模拟的用户的用户名、密码、域(机器名) private String _sImperUsername; private String _sImperPassword; private String _sImperDomain; // 记录模拟上下文 private WindowsImpersonationContext _imperContext; private IntPtr _adminToken; private IntPtr _dupeToken; // 是否已停止模拟 private Boolean _bClosed; /// <summary> /// 构造函数 /// </summary> /// <param name="impersonationUsername">所要模拟的用户的用户名</param> /// <param name="impersonationPassword">所要模拟的用户的密码</param> /// <param name="impersonationDomain">所要模拟的用户所在的域</param> public IdentityImpersonation(String impersonationUsername, String impersonationPassword, String impersonationDomain) { _sImperUsername = impersonationUsername; _sImperPassword = impersonationPassword; _sImperDomain = impersonationDomain; _adminToken = IntPtr.Zero; _dupeToken = IntPtr.Zero; _bClosed = true; } /// <summary> /// 析构函数 /// </summary> ~IdentityImpersonation() { if (!_bClosed) { StopImpersonate(); } } /// <summary> /// 开始身份角色模拟 /// </summary> /// <returns></returns> public Boolean BeginImpersonate() { Boolean bLogined = LogonUser(_sImperUsername, _sImperDomain, _sImperPassword, 2, 0, ref _adminToken); if (!bLogined) { return false; } Boolean bDuped = DuplicateToken(_adminToken, 2, ref _dupeToken); if (!bDuped) { return false; } WindowsIdentity fakeId = new WindowsIdentity(_dupeToken); _imperContext = fakeId.Impersonate(); _bClosed = false; return true; } /// <summary> /// 停止身分角色模拟。 /// </summary> public void StopImpersonate() { _imperContext.Undo(); CloseHandle(_dupeToken); CloseHandle(_adminToken); _bClosed = true; } }
public class ADUser { /// <summary> /// 用户名称 /// </summary> public string UserName { get; set; } /// <summary> /// 登录名 /// </summary> public string LoginName { get; set; } /// <summary> /// 密码 /// </summary> public string Password { get; set; } /// <summary> /// 用户所属部门 /// </summary> public string Department { get; set; } /// <summary> /// 部门是单位还是组 true单位false组 /// </summary> public bool IsOU { get; set; } /// <summary> /// 部门层级 /// </summary> public int Level { get; set; } public ADUser() { } public ADUser(string department, int level, string userName = "", string loginName = "", string password = "smxxh@2020", bool isOU = true) { this.UserName = userName; this.LoginName = loginName; this.Password = password; this.Department = department; this.IsOU = isOU; this.Level = level; } }