前段时间(因为懒得找具体的时间了)公司说让系统可以进行对AD域的操作,包括创建用户。于是上网查资料,了解何为AD域。还不知道的这边请https://www.cnblogs.com/cnjavahome/p/9029665.html。
网上有很多提供对AD域操作的帮助类,简称ADHelper.等会我也发一个。使用网上的帮助类的时候我遇到几个问题。这就是我为什么写这个随笔的原因。
问题1:创建用户的时候提示以下错误。
有几种原因:密码错误,不满足密码复杂度(长度至少7,且含有英文数字特殊符号),对账号启用的时候也会报这个错误。
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public static void EnableUser(DirectoryEntry de) { try { impersonate.BeginImpersonate(); de.Properties["userAccountControl"].Value = ADHelper.ADS_USER_FLAG_ENUM.ADS_UF_NORMAL_ACCOUNT | ADHelper.ADS_USER_FLAG_ENUM.ADS_UF_TRUSTED_FOR_DELEGATION | ADHelper.ADS_USER_FLAG_ENUM.ADS_UF_DONT_EXPIRE_PASSWD; de.CommitChanges(); impersonate.StopImpersonate(); de.Close(); } catch (Exception ex) { throw; } }
这个方法在本机的时候运行可以,但是到了客户测试那边还是报以上的错误,而且这个错误百度找不到,只好google,谁叫我不懂呢。查找了好久好久好久……发现了一个新的方式去启用这个方法就是这样
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
public static void EnableUser(string commonName) { try { //DomainName:填写域名, Administrator表示登录账户,123456密码。 PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, DomainName, "Administrator", "123456"); UserPrincipal userPrincipal = UserPrincipal.FindByIdentity (principalContext,commonName); userPrincipal.Enabled = true; //如果是禁用这里就改成false userPrincipal.Save(); } catch (Exception ex) { Console.WriteLine(ex.Message); } }
好了这里的启用错误改好了。
问题2:有空的时候加上去吧
后面放个我的ADHelper
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 using System; 2 using System.DirectoryServices; 3 using System.DirectoryServices.AccountManagement; 4 using System.Runtime.InteropServices; 5 using System.Security.Principal; 6 7 8 9 namespace SystemFrameworks.Helper 10 { 11 12 /// 13 14 /// 活动目录辅助类。封装一系列活动目录操作相关的方法。 15 16 /// 17 18 public sealed class ADHelper 19 { 20 21 /// 22 23 /// 域名 24 25 /// 26 27 private static string DomainName = "TEST.COM"; 28 29 /// 30 31 /// LDAP 地址 32 33 /// 34 35 private static string LDAPDomain = "CN=Schema,CN=Configuration,DC=test,DC=com"; 36 37 /// 38 39 /// LDAP绑定路径 40 41 /// 42 43 private static string ADPath = "LDAP://test.com"; 44 45 /// 46 47 /// 登录帐号 48 49 /// 50 51 private static string ADUser = "Administrator"; 52 53 /// 54 55 /// 登录密码 56 57 /// 58 59 private static string ADPassword = "123456"; 60 61 /// 62 63 /// 扮演类实例 64 65 /// 66 67 private static IdentityImpersonation impersonate = new IdentityImpersonation(ADUser, ADPassword, DomainName); 68 69 70 71 /// 72 73 /// 用户登录验证结果 74 75 /// 76 77 public enum LoginResult 78 { 79 80 /// 81 82 /// 正常登录 83 84 /// 85 86 LOGIN_USER_OK = 0, 87 88 /// 89 90 /// 用户不存在 91 92 /// 93 94 LOGIN_USER_DOESNT_EXIST, 95 96 /// 97 98 /// 用户帐号被禁用 99 100 /// 101 102 LOGIN_USER_ACCOUNT_INACTIVE, 103 104 /// 105 106 /// 用户密码不正确 107 108 /// 109 110 LOGIN_USER_PASSWORD_INCORRECT 111 112 } 113 114 115 116 /// 117 118 /// 用户属性定义标志 119 120 /// 121 122 public enum ADS_USER_FLAG_ENUM 123 { 124 125 /// 126 127 /// 登录脚本标志。如果通过 ADSI LDAP 进行读或写操作时,该标志失效。如果通过 ADSI WINNT,该标志为只读。 128 129 /// 130 131 ADS_UF_SCRIPT = 0X0001, 132 133 /// 134 135 /// 用户帐号禁用标志 136 137 /// 138 139 ADS_UF_ACCOUNTDISABLE = 0X0002, 140 141 /// 142 143 /// 主文件夹标志 144 145 /// 146 147 ADS_UF_HOMEDIR_REQUIRED = 0X0008, 148 149 /// 150 151 /// 过期标志 152 153 /// 154 155 ADS_UF_LOCKOUT = 0X0010, 156 157 /// 158 159 /// 用户密码不是必须的 160 161 /// 162 163 ADS_UF_PASSWD_NOTREQD = 0X0020, 164 165 /// 166 167 /// 密码不能更改标志 168 169 /// 170 171 ADS_UF_PASSWD_CANT_CHANGE = 0X0040, 172 173 /// 174 175 /// 使用可逆的加密保存密码 176 177 /// 178 179 ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED = 0X0080, 180 181 /// 182 183 /// 本地帐号标志 184 185 /// 186 187 ADS_UF_TEMP_DUPLICATE_ACCOUNT = 0X0100, 188 189 /// 190 191 /// 普通用户的默认帐号类型 192 193 /// 194 195 ADS_UF_NORMAL_ACCOUNT = 0X0200, 196 197 /// 198 199 /// 跨域的信任帐号标志 200 201 /// 202 203 ADS_UF_INTERDOMAIN_TRUST_ACCOUNT = 0X0800, 204 205 /// 206 207 /// 工作站信任帐号标志 208 209 /// 210 211 ADS_UF_WORKSTATION_TRUST_ACCOUNT = 0x1000, 212 213 /// 214 215 /// 服务器信任帐号标志 216 217 /// 218 219 ADS_UF_SERVER_TRUST_ACCOUNT = 0X2000, 220 221 /// 222 223 /// 密码永不过期标志 224 225 /// 226 227 ADS_UF_DONT_EXPIRE_PASSWD = 0X10000, 228 229 /// 230 231 /// MNS 帐号标志 232 233 /// 234 235 ADS_UF_MNS_LOGON_ACCOUNT = 0X20000, 236 237 /// 238 239 /// 交互式登录必须使用智能卡 240 241 /// 242 243 ADS_UF_SMARTCARD_REQUIRED = 0X40000, 244 245 /// 246 247 /// 当设置该标志时,服务帐号(用户或计算机帐号)将通过 Kerberos 委托信任 248 249 /// 250 251 ADS_UF_TRUSTED_FOR_DELEGATION = 0X80000, 252 253 /// 254 255 /// 当设置该标志时,即使服务帐号是通过 Kerberos 委托信任的,敏感帐号不能被委托 256 257 /// 258 259 ADS_UF_NOT_DELEGATED = 0X100000, 260 261 /// 262 263 /// 此帐号需要 DES 加密类型 264 265 /// 266 267 ADS_UF_USE_DES_KEY_ONLY = 0X200000, 268 269 /// 270 271 /// 不要进行 Kerberos 预身份验证 272 273 /// 274 275 ADS_UF_DONT_REQUIRE_PREAUTH = 0X4000000, 276 277 /// 278 279 /// 用户密码过期标志 280 281 /// 282 283 ADS_UF_PASSWORD_EXPIRED = 0X800000, 284 285 /// 286 287 /// 用户帐号可委托标志 288 289 /// 290 291 ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0X1000000 292 293 } 294 295 296 297 public ADHelper() 298 { 299 300 // 301 302 } 303 304 305 306 #region GetDirectoryObject 307 308 309 310 /// 311 312 /// 获得DirectoryEntry对象实例,以管理员登陆AD 313 314 /// 315 316 /// 317 318 private static DirectoryEntry GetDirectoryObject() 319 { 320 321 DirectoryEntry entry = new DirectoryEntry(ADPath, ADUser, ADPassword, AuthenticationTypes.Secure); 322 323 return entry; 324 325 } 326 public static bool Ver() 327 { 328 try 329 { 330 DirectoryEntry de = GetDirectoryObject(); 331 de.RefreshCache(); 332 return true; 333 } 334 catch (Exception ex) 335 { 336 throw; 337 } 338 return false; 339 } 340 341 342 343 /// 344 345 /// 根据指定用户名和密码获得相应DirectoryEntry实体 346 347 /// 348 349 /// 350 351 /// 352 353 /// 354 355 private static DirectoryEntry GetDirectoryObject(string userName, string password) 356 { 357 358 DirectoryEntry entry = new DirectoryEntry(ADPath, userName, password, AuthenticationTypes.None); 359 360 return entry; 361 362 } 363 364 365 366 /// 367 368 /// i.e. /CN=Users,DC=creditsights, DC=cyberelves, DC=Com 369 370 /// 371 372 /// 373 374 /// 375 376 private static DirectoryEntry GetDirectoryObject(string domainReference) 377 { 378 379 DirectoryEntry entry = new DirectoryEntry(ADPath + domainReference, ADUser, ADPassword, AuthenticationTypes.Secure); 380 381 return entry; 382 383 } 384 385 386 387 /// 388 389 /// 获得以UserName,Password创建的DirectoryEntry 390 391 /// 392 393 /// 394 395 /// 396 397 /// 398 399 /// 400 401 private static DirectoryEntry GetDirectoryObject(string domainReference, string userName, string password) 402 { 403 404 DirectoryEntry entry = new DirectoryEntry(ADPath + domainReference, userName, password, AuthenticationTypes.Secure); 405 406 return entry; 407 408 } 409 410 411 412 #endregion 413 414 415 416 #region GetDirectoryEntry 417 418 419 420 /// 421 422 /// 根据用户公共名称取得用户的 对象 423 424 /// 425 426 /// 用户公共名称 427 428 /// 如果找到该用户,则返回用户的 对象;否则返回 null 429 430 public static DirectoryEntry GetDirectoryEntry(string commonName) 431 { 432 433 DirectoryEntry de = GetDirectoryObject(); 434 435 DirectorySearcher deSearch = new DirectorySearcher(de); 436 437 deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(cn=" + commonName + "))"; 438 439 deSearch.SearchScope = SearchScope.Subtree; 440 441 442 443 try 444 { 445 446 SearchResult result = deSearch.FindOne(); 447 448 de = new DirectoryEntry(result.Path); 449 450 return de; 451 452 } 453 454 catch 455 { 456 457 return null; 458 459 } 460 461 } 462 463 464 465 /// 466 467 /// 根据用户公共名称和密码取得用户的 对象。 468 469 /// 470 471 /// 用户公共名称 472 473 /// 用户密码 474 475 /// 如果找到该用户,则返回用户的 对象;否则返回 null 476 477 public static DirectoryEntry GetDirectoryEntry(string commonName, string password) 478 { 479 480 DirectoryEntry de = GetDirectoryObject(commonName, password); 481 482 DirectorySearcher deSearch = new DirectorySearcher(de); 483 484 deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(cn=" + commonName + "))"; 485 486 deSearch.SearchScope = SearchScope.Subtree; 487 488 489 490 try 491 { 492 493 SearchResult result = deSearch.FindOne(); 494 495 de = new DirectoryEntry(result.Path); 496 497 return de; 498 499 } 500 501 catch 502 { 503 504 return null; 505 506 } 507 508 } 509 510 511 512 /// 513 514 /// 根据用户帐号称取得用户的 对象 515 516 /// 517 518 /// 用户帐号名 519 520 /// 如果找到该用户,则返回用户的 对象;否则返回 null 521 522 public static DirectoryEntry GetDirectoryEntryByAccount(string sAMAccountName) 523 { 524 525 DirectoryEntry de = GetDirectoryObject(); 526 527 DirectorySearcher deSearch = new DirectorySearcher(de); 528 529 deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(sAMAccountName=" + sAMAccountName + "))"; 530 531 deSearch.SearchScope = SearchScope.Subtree; 532 533 534 535 try 536 { 537 538 SearchResult result = deSearch.FindOne(); 539 540 de = new DirectoryEntry(result.Path); 541 542 return de; 543 544 } 545 546 catch 547 { 548 549 return null; 550 551 } 552 553 } 554 555 556 557 /// 558 559 /// 根据用户帐号和密码取得用户的 对象 560 561 /// 562 563 /// 用户帐号名 564 565 /// 用户密码 566 567 /// 如果找到该用户,则返回用户的 对象;否则返回 null 568 569 public static DirectoryEntry GetDirectoryEntryByAccount(string sAMAccountName, string password) 570 { 571 572 DirectoryEntry de = GetDirectoryEntryByAccount(sAMAccountName); 573 574 if (de != null) 575 { 576 577 string commonName = de.Properties["cn"][0].ToString(); 578 579 580 581 if (GetDirectoryEntry(commonName, password) != null) 582 583 return GetDirectoryEntry(commonName, password); 584 585 else 586 587 return null; 588 589 } 590 591 else 592 { 593 594 return null; 595 596 } 597 598 } 599 600 601 602 /// 603 604 /// 根据组名取得用户组的 对象 605 606 /// 607 608 /// 组名 609 610 /// 611 612 public static DirectoryEntry GetDirectoryEntryOfGroup(string groupName) 613 { 614 615 DirectoryEntry de = GetDirectoryObject(); 616 617 DirectorySearcher deSearch = new DirectorySearcher(de); 618 619 deSearch.Filter = "(&(objectClass=group)(cn=" + groupName + "))"; 620 621 deSearch.SearchScope = SearchScope.Subtree; 622 623 624 625 try 626 { 627 628 SearchResult result = deSearch.FindOne(); 629 630 de = new DirectoryEntry(result.Path); 631 632 return de; 633 634 } 635 636 catch 637 { 638 639 return null; 640 641 } 642 643 } 644 645 646 647 #endregion 648 649 650 651 #region GetProperty 652 653 654 655 /// 656 657 /// 获得指定 指定属性名对应的值 658 659 /// 660 661 /// 662 663 /// 属性名称 664 665 /// 属性值 666 667 public static string GetProperty(DirectoryEntry de, string propertyName) 668 { 669 670 if (de.Properties.Contains(propertyName)) 671 { 672 673 return de.Properties[propertyName][0].ToString(); 674 675 } 676 677 else 678 { 679 680 return string.Empty; 681 682 } 683 684 } 685 686 687 688 /// 689 690 /// 获得指定搜索结果 中指定属性名对应的值 691 692 /// 693 694 /// 695 696 /// 属性名称 697 698 /// 属性值 699 700 public static string GetProperty(SearchResult searchResult, string propertyName) 701 { 702 703 if (searchResult.Properties.Contains(propertyName)) 704 { 705 706 return searchResult.Properties[propertyName][0].ToString(); 707 708 } 709 710 else 711 { 712 713 return string.Empty; 714 715 } 716 717 } 718 719 720 721 #endregion 722 723 724 725 /// 726 727 /// 设置指定 的属性值 728 729 /// 730 731 /// 732 733 /// 属性名称 734 735 /// 属性值 736 737 public static void SetProperty(DirectoryEntry de, string propertyName, string propertyValue) 738 { 739 740 if (propertyValue != string.Empty || propertyValue != "" || propertyValue != null) 741 { 742 743 if (de.Properties.Contains(propertyName)) 744 { 745 746 de.Properties[propertyName][0] = propertyValue; 747 748 } 749 750 else 751 { 752 753 de.Properties[propertyName].Add(propertyValue); 754 755 } 756 757 } 758 759 } 760 761 762 763 /// 764 765 /// 创建新的用户 766 767 /// 768 769 /// DN 位置。例如:OU=共享平台 或 CN=Users 770 771 /// 公共名称 772 773 /// 帐号 774 775 /// 密码 776 777 /// 778 779 public static DirectoryEntry CreateNewUser(string ldapDN, string commonName, string sAMAccountName, string password) 780 { 781 782 DirectoryEntry entry = GetDirectoryObject(); 783 784 DirectoryEntry subEntry = entry.Children.Find(ldapDN); 785 786 DirectoryEntry deUser = subEntry.Children.Add("CN=" + commonName, "user"); 787 788 deUser.Properties["sAMAccountName"].Value = sAMAccountName; 789 790 deUser.CommitChanges(); 791 deUser.AuthenticationType = AuthenticationTypes.Secure; 792 object[] PSD = new object[] { SetSecurePassword() }; 793 object ret = deUser.Invoke("SetPassword", PSD); 794 // ADHelper.SetPassword(commonName, password); 795 ADHelper.EnableUser(commonName); 796 797 798 deUser.Close(); 799 800 return deUser; 801 802 } 803 804 public static string SetSecurePassword() 805 { 806 //RandomPassword rp = new RandomPassword(); 807 return "qwe12d."; 808 } 809 810 811 public void SetPassword(DirectoryEntry newuser) 812 { 813 814 815 newuser.AuthenticationType = AuthenticationTypes.Secure; 816 object[] password = new object[] { SetSecurePassword() }; 817 object ret = newuser.Invoke("SetPassword", password); 818 newuser.CommitChanges(); 819 newuser.Close(); 820 821 } 822 823 public static bool IsRepeat(string commonName) 824 { 825 PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, DomainName, "Administrator", "123456"); 826 UserPrincipal userPrincipal = UserPrincipal.FindByIdentity 827 (principalContext, commonName); 828 if (userPrincipal==null) 829 { 830 return false; 831 } 832 try 833 { 834 return (bool)userPrincipal.Enabled; 835 } 836 finally { 837 if (userPrincipal!=null) 838 { 839 840 userPrincipal.Dispose(); 841 } 842 if (principalContext!=null) 843 { 844 845 principalContext.Dispose(); 846 } 847 } 848 849 850 // userPrincipal.Save(); 851 } 852 /// 853 854 /// 创建新的用户。默认创建在 Users 单元下。 855 856 /// 857 858 /// 公共名称 859 860 /// 帐号 861 862 /// 密码 863 864 /// 865 866 public static DirectoryEntry CreateNewUser(string commonName, string sAMAccountName, string password) 867 { 868 869 return CreateNewUser("CN=Users", commonName, sAMAccountName, password); 870 871 } 872 873 874 875 /// 876 877 /// 判断指定公共名称的用户是否存在 878 879 /// 880 881 /// 用户公共名称 882 883 /// 如果存在,返回 true;否则返回 false 884 885 public static bool IsUserExists(string commonName) 886 { 887 888 DirectoryEntry de = GetDirectoryObject(); 889 890 DirectorySearcher deSearch = new DirectorySearcher(de); 891 892 deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(cn=" + commonName + "))"; // LDAP 查询串 893 894 SearchResultCollection results = deSearch.FindAll(); 895 896 897 898 if (results.Count == 0) 899 900 return false; 901 902 else 903 904 return true; 905 906 } 907 908 909 910 /// 911 912 /// 判断用户帐号是否激活 913 914 /// 915 916 /// 用户帐号属性控制器 917 918 /// 如果用户帐号已经激活,返回 true;否则返回 false 919 920 public static bool IsAccountActive(int userAccountControl) 921 { 922 923 int userAccountControl_Disabled = Convert.ToInt32(ADS_USER_FLAG_ENUM.ADS_UF_ACCOUNTDISABLE); 924 925 int flagExists = userAccountControl & userAccountControl_Disabled; 926 927 928 929 if (flagExists > 0) 930 931 return false; 932 933 else 934 935 return true; 936 937 } 938 939 940 941 /// 942 943 /// 判断用户与密码是否足够以满足身份验证进而登录 944 945 /// 946 947 /// 用户公共名称 948 949 /// 密码 950 951 /// 如能可正常登录,则返回 true;否则返回 false 952 953 public static LoginResult Login(string commonName, string password) 954 { 955 956 DirectoryEntry de = GetDirectoryEntry(commonName,password); 957 958 959 960 if (de != null) 961 { 962 963 // 必须在判断用户密码正确前,对帐号激活属性进行判断;否则将出现异常。 964 965 int userAccountControl = Convert.ToInt32(de.Properties["userAccountControl"][0]); 966 967 de.Close(); 968 969 970 971 if (!IsAccountActive(userAccountControl)) 972 973 return LoginResult.LOGIN_USER_ACCOUNT_INACTIVE; 974 975 976 977 if (GetDirectoryEntry(commonName, password) != null) 978 979 return LoginResult.LOGIN_USER_OK; 980 981 else 982 983 return LoginResult.LOGIN_USER_PASSWORD_INCORRECT; 984 985 } 986 987 else 988 { 989 990 return LoginResult.LOGIN_USER_DOESNT_EXIST; 991 992 } 993 994 } 995 996 997 998 /// 999 1000 /// 判断用户帐号与密码是否足够以满足身份验证进而登录 1001 1002 /// 1003 1004 /// 用户帐号 1005 1006 /// 密码 1007 1008 /// 如能可正常登录,则返回 true;否则返回 false 1009 1010 public static LoginResult LoginByAccount(string sAMAccountName, string password) 1011 { 1012 1013 DirectoryEntry de = GetDirectoryEntryByAccount(sAMAccountName); 1014 1015 1016 1017 if (de != null) 1018 { 1019 1020 // 必须在判断用户密码正确前,对帐号激活属性进行判断;否则将出现异常。 1021 1022 int userAccountControl = Convert.ToInt32(de.Properties["userAccountControl"][0]); 1023 1024 de.Close(); 1025 1026 1027 1028 if (!IsAccountActive(userAccountControl)) 1029 1030 return LoginResult.LOGIN_USER_ACCOUNT_INACTIVE; 1031 1032 1033 1034 if (GetDirectoryEntryByAccount(sAMAccountName, password) != null) 1035 1036 return LoginResult.LOGIN_USER_OK; 1037 1038 else 1039 1040 return LoginResult.LOGIN_USER_PASSWORD_INCORRECT; 1041 1042 } 1043 1044 else 1045 { 1046 1047 return LoginResult.LOGIN_USER_DOESNT_EXIST; 1048 1049 } 1050 1051 } 1052 1053 1054 1055 /// 1056 1057 /// 设置用户密码,管理员可以通过它来修改指定用户的密码。 1058 1059 /// 1060 1061 /// 用户公共名称 1062 1063 /// 用户新密码 1064 1065 public static void SetPassword(string commonName, string newPassword) 1066 { 1067 1068 DirectoryEntry de = GetDirectoryObject(commonName); 1069 1070 1071 1072 // 模拟超级管理员,以达到有权限修改用户密码 1073 1074 impersonate.BeginImpersonate(); 1075 1076 de.Invoke("SetPassword", new object[] { newPassword }); 1077 1078 impersonate.StopImpersonate(); 1079 1080 1081 1082 de.Close(); 1083 1084 1085 //de.AuthenticationType = AuthenticationTypes.Secure; 1086 //object[] password = new object[] { newPassword }; 1087 //object ret = de.Invoke("SetPassword", password); 1088 //de.CommitChanges(); 1089 //de.Close(); 1090 1091 } 1092 1093 1094 1095 private static DirectoryEntry GetUser(string UserName, string oldpsw) 1096 { 1097 1098 DirectoryEntry de = GetDirectoryObject(); 1099 DirectorySearcher deSearch = new DirectorySearcher(); 1100 deSearch.SearchRoot = de; 1101 1102 deSearch.Filter = "(&(objectClass=user)(SAMAccountName=" + UserName + "))"; 1103 deSearch.SearchScope = SearchScope.Subtree; 1104 SearchResult results = deSearch.FindOne(); 1105 1106 if (!(results == null)) 1107 { 1108 // **THIS IS THE MOST IMPORTANT LINE** 1109 de = new DirectoryEntry(results.Path, "username", "password", AuthenticationTypes.Secure); 1110 return de; 1111 } 1112 else 1113 { 1114 return null; 1115 } 1116 } 1117 1118 1119 1120 public static bool ChangePassword(string UserName, string strOldPassword, string strNewPassword) 1121 { 1122 1123 bool passwordChanged = false; 1124 1125 DirectoryEntry oDE = GetUser(UserName, strOldPassword); 1126 1127 if (oDE != null) 1128 { 1129 1130 // Change the password. 1131 oDE.Invoke("ChangePassword", new object[] { strOldPassword, strNewPassword }); 1132 passwordChanged = true; 1133 1134 } 1135 return passwordChanged; 1136 } 1137 1138 1139 1140 /// 1141 1142 /// 设置帐号密码,管理员可以通过它来修改指定帐号的密码。 1143 1144 /// 1145 1146 /// 用户帐号 1147 1148 /// 用户新密码 1149 1150 public static void SetPasswordByAccount(string sAMAccountName, string newPassword) 1151 { 1152 1153 DirectoryEntry de = GetDirectoryEntryByAccount(sAMAccountName); 1154 1155 1156 1157 // 模拟超级管理员,以达到有权限修改用户密码 1158 1159 IdentityImpersonation impersonate = new IdentityImpersonation(ADUser, ADPassword, DomainName); 1160 1161 impersonate.BeginImpersonate(); 1162 1163 de.Invoke("SetPassword", new object[] { newPassword }); 1164 1165 impersonate.StopImpersonate(); 1166 1167 1168 1169 de.Close(); 1170 1171 } 1172 1173 1174 1175 /// 1176 1177 /// 修改用户密码 1178 1179 /// 1180 1181 /// 用户公共名称 1182 1183 /// 旧密码 1184 1185 /// 新密码 1186 1187 public static void ChangeUserPassword(string commonName, string oldPassword, string newPassword) 1188 { 1189 1190 // to-do: 需要解决密码策略问题 1191 1192 DirectoryEntry oUser = GetDirectoryEntry(commonName); 1193 1194 oUser.Invoke("ChangePassword", new Object[] { oldPassword, newPassword }); 1195 1196 oUser.Close(); 1197 1198 } 1199 1200 1201 1202 /// 1203 1204 /// 启用指定公共名称的用户 1205 1206 /// 1207 1208 /// 用户公共名称 1209 1210 public static void EnableUser(string commonName) 1211 { 1212 1213 try 1214 { 1215 //DomainName:填写域名, Administrator表示登录账户,123456密码。 1216 PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, DomainName, "Administrator", "123456"); 1217 UserPrincipal userPrincipal = UserPrincipal.FindByIdentity 1218 (principalContext,commonName); 1219 1220 userPrincipal.Enabled = true; 1221 //如果是禁用这里就改成false 1222 userPrincipal.Save(); 1223 1224 } 1225 catch (Exception ex) 1226 { 1227 Console.WriteLine(ex.Message); 1228 } 1229 } 1230 1231 1232 1233 /// 1234 1235 /// 启用指定 的用户 1236 1237 /// 1238 1239 /// 1240 1241 public static void EnableUser(DirectoryEntry de) 1242 { 1243 try 1244 { 1245 impersonate.BeginImpersonate(); 1246 de.Properties["userAccountControl"].Value = ADHelper.ADS_USER_FLAG_ENUM.ADS_UF_NORMAL_ACCOUNT | ADHelper.ADS_USER_FLAG_ENUM.ADS_UF_TRUSTED_FOR_DELEGATION | ADHelper.ADS_USER_FLAG_ENUM.ADS_UF_DONT_EXPIRE_PASSWD; 1247 de.CommitChanges(); 1248 1249 impersonate.StopImpersonate(); 1250 1251 de.Close(); 1252 1253 } 1254 catch (Exception ex) 1255 { 1256 throw; 1257 } 1258 1259 } 1260 1261 1262 1263 /// 1264 1265 /// 禁用指定公共名称的用户 1266 1267 /// 1268 1269 /// 用户公共名称 1270 1271 public static void DisableUser(string commonName) 1272 { 1273 1274 //DisableUser(GetDirectoryEntry(commonName)); 1275 try 1276 { 1277 // PrincipalContext principalContext = new PrincipalContext(ContextType.Domain); 1278 PrincipalContext principalContext = new PrincipalContext(ContextType.Domain, DomainName, "Administrator", "123456"); 1279 UserPrincipal userPrincipal = UserPrincipal.FindByIdentity 1280 (principalContext, commonName); 1281 1282 userPrincipal.Enabled = false; 1283 1284 userPrincipal.Save(); 1285 1286 } 1287 catch (Exception ex) 1288 { 1289 Console.WriteLine(ex.Message); 1290 } 1291 } 1292 1293 1294 1295 /// 1296 1297 /// 禁用指定 的用户 1298 1299 /// 1300 1301 /// 1302 1303 public static void DisableUser(DirectoryEntry de) 1304 { 1305 1306 impersonate.BeginImpersonate(); 1307 1308 de.Properties["userAccountControl"][0] = ADHelper.ADS_USER_FLAG_ENUM.ADS_UF_NORMAL_ACCOUNT | ADHelper.ADS_USER_FLAG_ENUM.ADS_UF_DONT_EXPIRE_PASSWD | ADHelper.ADS_USER_FLAG_ENUM.ADS_UF_ACCOUNTDISABLE; 1309 1310 de.CommitChanges(); 1311 1312 impersonate.StopImpersonate(); 1313 1314 de.Close(); 1315 1316 } 1317 1318 1319 1320 /// 1321 1322 /// 将指定的用户添加到指定的组中。默认为 Users 下的组和用户。 1323 1324 /// 1325 1326 /// 用户公共名称 1327 1328 /// 组名 1329 1330 public static void AddUserToGroup(string userCommonName, string groupName) 1331 { 1332 1333 DirectoryEntry oGroup = GetDirectoryEntryOfGroup(groupName); 1334 1335 DirectoryEntry oUser = GetDirectoryEntry(userCommonName); 1336 1337 1338 1339 impersonate.BeginImpersonate(); 1340 1341 oGroup.Properties["member"].Add(oUser.Properties["distinguishedName"].Value); 1342 1343 oGroup.CommitChanges(); 1344 1345 impersonate.StopImpersonate(); 1346 1347 1348 1349 oGroup.Close(); 1350 1351 oUser.Close(); 1352 1353 } 1354 1355 1356 1357 /// 1358 1359 /// 将用户从指定组中移除。默认为 Users 下的组和用户。 1360 1361 /// 1362 1363 /// 用户公共名称 1364 1365 /// 组名 1366 1367 public static void RemoveUserFromGroup(string userCommonName, string groupName) 1368 { 1369 1370 DirectoryEntry oGroup = GetDirectoryEntryOfGroup(groupName); 1371 1372 DirectoryEntry oUser = GetDirectoryEntry(userCommonName); 1373 1374 1375 1376 impersonate.BeginImpersonate(); 1377 1378 oGroup.Properties["member"].Remove(oUser.Properties["distinguishedName"].Value); 1379 1380 oGroup.CommitChanges(); 1381 1382 impersonate.StopImpersonate(); 1383 1384 1385 1386 oGroup.Close(); 1387 1388 oUser.Close(); 1389 1390 } 1391 1392 1393 1394 } 1395 1396 1397 1398 /// 1399 1400 /// 用户模拟角色类。实现在程序段内进行用户角色模拟。 1401 1402 /// 1403 1404 public class IdentityImpersonation 1405 { 1406 1407 [DllImport("advapi32.dll", SetLastError = true)] 1408 1409 public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); 1410 1411 1412 1413 [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)] 1414 1415 public extern static bool DuplicateToken(IntPtr ExistingTokenHandle, int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle); 1416 1417 1418 1419 [DllImport("kernel32.dll", CharSet = CharSet.Auto)] 1420 1421 public extern static bool CloseHandle(IntPtr handle); 1422 1423 1424 1425 // 要模拟的用户的用户名、密码、域(机器名) 1426 1427 private String _sImperUsername; 1428 1429 private String _sImperPassword; 1430 1431 private String _sImperDomain; 1432 1433 // 记录模拟上下文 1434 1435 private WindowsImpersonationContext _imperContext; 1436 1437 private IntPtr _adminToken; 1438 1439 private IntPtr _dupeToken; 1440 1441 // 是否已停止模拟 1442 1443 private Boolean _bClosed; 1444 1445 1446 1447 /// 1448 1449 /// 构造函数 1450 1451 /// 1452 1453 /// 所要模拟的用户的用户名 1454 1455 /// 所要模拟的用户的密码 1456 1457 /// 所要模拟的用户所在的域 1458 1459 public IdentityImpersonation(String impersonationUsername, String impersonationPassword, String impersonationDomain) 1460 { 1461 1462 _sImperUsername = impersonationUsername; 1463 1464 _sImperPassword = impersonationPassword; 1465 1466 _sImperDomain = impersonationDomain; 1467 1468 1469 1470 _adminToken = IntPtr.Zero; 1471 1472 _dupeToken = IntPtr.Zero; 1473 1474 _bClosed = true; 1475 1476 } 1477 1478 1479 1480 /// 1481 1482 /// 析构函数 1483 1484 /// 1485 1486 ~IdentityImpersonation() 1487 { 1488 1489 if (!_bClosed) 1490 { 1491 1492 StopImpersonate(); 1493 1494 } 1495 1496 } 1497 1498 1499 1500 /// 1501 1502 /// 开始身份角色模拟。 1503 1504 /// 1505 1506 /// 1507 1508 public Boolean BeginImpersonate() 1509 { 1510 1511 Boolean bLogined = LogonUser(_sImperUsername, _sImperDomain, _sImperPassword, 2, 0, ref _adminToken); 1512 1513 1514 1515 if (!bLogined) 1516 { 1517 1518 return false; 1519 1520 } 1521 1522 1523 1524 Boolean bDuped = DuplicateToken(_adminToken, 2, ref _dupeToken); 1525 1526 1527 1528 if (!bDuped) 1529 { 1530 1531 return false; 1532 1533 } 1534 1535 1536 1537 WindowsIdentity fakeId = new WindowsIdentity(_dupeToken); 1538 1539 _imperContext = fakeId.Impersonate(); 1540 1541 1542 1543 _bClosed = false; 1544 1545 1546 1547 return true; 1548 1549 } 1550 1551 1552 /// 1553 1554 /// 停止身分角色模拟。 1555 1556 /// 1557 1558 public void StopImpersonate() 1559 { 1560 1561 _imperContext.Undo(); 1562 1563 CloseHandle(_dupeToken); 1564 1565 CloseHandle(_adminToken); 1566 1567 _bClosed = true; 1568 1569 } 1570 1571 } 1572 }