程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> AD賬號操作C#示例代碼(二)——檢查密碼將過期的用戶

AD賬號操作C#示例代碼(二)——檢查密碼將過期的用戶

編輯:C#入門知識

本文接著和大家分享AD賬號操作,這次開發一個簡單的檢查密碼將過期用戶的小工具。           首先,新建一個用戶實體類,屬性是我們要取的用戶信息。     復制代碼  public class UserInfo     {         /// <summary>         /// sAM帳戶名稱         /// </summary>         public string SamAccountName { get; set; }         /// <summary>         /// 名稱         /// </summary>         public string Name { get; set; }         /// <summary>         /// 郵箱         /// </summary>         public string Mail { get; set; }         /// <summary>         /// 已禁用         /// </summary>         public bool IsDisabled { get; set; }         /// <summary>         /// 設置為密碼永不過期         /// </summary>         public bool IsPasswordNeverExpire { get; set; }         /// <summary>         /// 系統密碼過期設置天數         /// </summary>         public long MaxPasswordAge { get; set; }         /// <summary>         /// 剩余過期天數         /// </summary>         public double? SurplusPasswordExpirationDays {             get              {                 return PasswordExpirationDate.HasValue ? (Math.Round((PasswordExpirationDate.Value.Subtract(DateTime.Now).TotalDays),2)) : default(double?);              }         }         /// <summary>         /// 最近密碼修改時間         /// </summary>         public DateTime PasswordLastSet { get; set; }         /// <summary>         /// 密碼過期時間         /// </summary>         public DateTime? PasswordExpirationDate { get; set; }     } 復制代碼      然後是搜索用戶信息的方法。   復制代碼 private IEnumerable<UserInfo> SearchUsers(string path, string username, string password, string sAMAccountName, string displayName, bool isDisabled, bool IsPasswordNeverExpire, long[] surplusExpirationDays)         {             using (DirectoryEntry directoryEntry = new DirectoryEntry(path, username, password))             {                 using (DirectorySearcher directorySearcher = new DirectorySearcher(directoryEntry, @"&(objectCategory=person)(objectClass=user))", new string[] { "name", "sAMAccountName", "userAccountcontrol", "pwdLastSet", "mail" }, SearchScope.Subtree) { PageSize = 1000 })                 {                     using (SearchResultCollection userResultCollection = directorySearcher.FindAll())                     {                         foreach (SearchResult userResult in userResultCollection)                         {                             UserInfo userInfo = new UserInfo();                             //TODO: 賦值                             yield return userInfo;                         }                     }                 }             }         } 復制代碼      這次我們主要用DirectorySearcher類:SearchRoot是搜索的DirectoryEntry根節點;SearchScope屬性是搜索的范圍,是個SearchScope枚舉:Base(限於基對象)、OneLevel(搜索基對象的直接子對象,但不搜索基對象)、Subtree(搜索整個子樹,包括基對象及其所有子對象)。我們要在指定的OU下搜索用戶,所以選擇子樹Subtree。        DirectorySearcher類的Filter屬性是過濾條件,搜索用戶就是“&(objectCategory=person)(objectClass=user))"。我們可以把一些查詢條件放在這裡,減少搜索結果的返回行數:   復制代碼                     directorySearcher.SearchScope = SearchScope.Subtree;                     List<string> filterItems = new List<string>();                     if (!string.IsNullOrEmpty(sAMAccountName))                     {                         filterItems.Add(string.Format(@"(sAMAccountName={0})", sAMAccountName));                     }                     if (!string.IsNullOrEmpty(displayName))                     {                         filterItems.Add(string.Format(@"(name={0})", displayName));                     }                     if (!isDisabled)                     {                         filterItems.Add(@"(!(userAccountcontrol=514))");                     }                     if (!IsPasswordNeverExpire)                     {                         filterItems.Add(@"(!(userAccountcontrol=66048))");                     }                     if (surplusExpirationDays != null && surplusExpirationDays.Length > 0)                     {                         StringBuilder surplusExpirationDaysFilter = new StringBuilder(@"(|");                         DateTime now = DateTime.Now;                         foreach (long surplusExpirationDay in surplusExpirationDays)                         {                             DateTime passwordExpirationDate = now.AddDays(surplusExpirationDay);                             DateTime passwordLastSet = passwordExpirationDate.AddDays(-1 * maxPwdAge);                             if (surplusExpirationDay != 0)                             {                                 surplusExpirationDaysFilter.AppendFormat("(&(pwdLastSet>={0})(pwdLastSet<={1}))", passwordLastSet.ToFileTime().ToString(), passwordLastSet.AddDays(1).AddSeconds(-1).ToFileTime().ToString());                             }                             else                             {                                 surplusExpirationDaysFilter.AppendFormat("(pwdLastSet<={0})(pwdLastSet=0)", passwordLastSet.AddDays(1).AddSeconds(-1).ToFileTime().ToString());                             }                        }                         surplusExpirationDaysFilter.Append(@")");                         filterItems.Add(surplusExpirationDaysFilter.ToString());                     }                     directorySearcher.Filter = string.Format(@"(&{0}(objectCategory=person)(objectClass=user))", string.Concat(filterItems)); 復制代碼      但是帳戶已禁用和密碼永不過期這些屬性是保存在一個userAccountcontrol的整型裡,同樣的已禁用帳戶userAccountcontrol值可能不只一個。我現在還沒辦法把對它們的過濾寫在Filter裡(哪位高手知道怎麼寫望指點),所以我只能用C#代碼再在本地內存過濾一下了。   userInfo.IsPasswordNeverExpire = Convert.ToBoolean(userAccountControl & 0x10000); userInfo.IsDisabled = Convert.ToBoolean(userAccountControl & 0x0002); if ((isDisabled == userInfo.IsDisabled) && (IsPasswordNeverExpire == userInfo.IsPasswordNeverExpire)) {      yield return userInfo; }      Filter語法請參考:http://msdn.microsoft.com/en-us/library/aa746475.aspx        DirectorySearcher類的PropertiesToLoad屬性是要檢索的屬性列表,這個就相當於我們訪問數據庫時寫SQL語句裡SELECT後面的東西,最好按需指定,盡量不寫“SELECT *”; 還有DirectorySearcher類的PageSize屬性,如果要返回所有數據可以設為1000,否則是只返回1000條的。    directorySearcher.PropertiesToLoad.AddRange(new string[] { "name", "sAMAccountName", "userAccountcontrol", "pwdLastSet", "mail" });  directorySearcher.PageSize = 1000;       更多DirectorySearcher類屬性請參考:http://msdn.microsoft.com/zh-cn/library/System.DirectoryServices.DirectorySearcher_properties(v=vs.80).aspx         用戶密碼的過期日期可以通過DirectoryEntry對象的InvokeGet方法獲得,不過要加載一次DirectoryEntry的話,總覺得很浪費!       using (DirectoryEntry resultDirectoryEntry = userResult.GetDirectoryEntry())     {         userInfo.PasswordExpirationDate = DateTime.Parse(resultDirectoryEntry.InvokeGet("PasswordExpirationDate").ToString());     }        所以我還是願意自己算一下,用最近密碼設置時間+系統設置的密碼過期天數。最近密碼設置時間對應“pwdLastSet”,如果用DirectoryEntry對象的Properties取,那是個“System.__ComObject”類型值,幸好SearchResult對象的“pwdLastSet”可以直接取為long,這個值是Windows文件時間,可以再轉為本地時間。   long fileTime = (userResult.Properties["pwdLastSet"][0] as long?).GetValueOrDefault(); userInfo.PasswordLastSet = DateTime.FromFileTime(fileTime);       系統密碼過期天數是通過組策略設置的,可以在OU路徑下通過“maxPwdAge”屬性獲取,SearchResult對象的“maxPwdAge”也可以直接取為long。   復制代碼  directorySearcher.SearchScope = SearchScope.Base;  directorySearcher.Filter = @"(objectClass=*)";  directorySearcher.PropertiesToLoad.Add("maxPwdAge");  SearchResult ouResult = directorySearcher.FindOne();  long maxPwdAge = 0;  if (ouResult.Properties.Contains("maxPwdAge"))  {       maxPwdAge = TimeSpan.FromTicks((long)ouResult.Properties["maxPwdAge"][0]).Days * -1;  } 復制代碼       最後,用戶的密碼過期就可以這麼求了!    userInfo.MaxPasswordAge = maxPwdAge;  if (!userInfo.IsPasswordNeverExpire)  {       userInfo.PasswordExpirationDate = userInfo.PasswordLastSet.AddDays(userInfo.MaxPasswordAge);  }       查詢用戶信息OK,剩下貼段導出用戶信息的代碼:     復制代碼                    string connectionString = string.Format("Provider = Microsoft.ACE.OLEDB.12.0;Data Source ={0};Extended Properties='Excel 12.0 Xml;HDR=YES'", fileName);                     using (OleDbConnection oleDbConnection = new OleDbConnection(connectionString))                     {                         oleDbConnection.Open();                         using (OleDbCommand oleDbCommand = new OleDbCommand())                         {                             oleDbCommand.Connection = oleDbConnection;                             //const string sqlCreateTable = @"CREATE TABLE [Sheet1$] ([登錄名] TEXT,[顯示名] TEXT,[郵箱] TEXT,[已禁用] TEXT,[密碼永不過期] TEXT,[密碼過期設置天數] TEXT,[密碼最近設置時間] TEXT,[密碼過期時間] TEXT,[剩余密碼過期天數] TEXT)";                             //oleDbCommand.CommandText = sqlCreateTable;                             //oleDbCommand.ExecuteNonQuery();                             foreach (var user in users)                             {                                 oleDbCommand.CommandText = string.Format(@"INSERT INTO [Sheet1$]([登錄名], [顯示名], [郵箱],[已禁用], [密碼永不過期], [密碼過期設置天數],[密碼最近設置時間],[密碼過期時間],[剩余密碼過期天數]) VALUES ('{0}','{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}');", user.SamAccountName, user.Name, user.Mail, user.IsDisabled ? "是" : "否", user.IsPasswordNeverExpire ? "是" : "否", user.MaxPasswordAge.ToString(), user.PasswordLastSet.ToString(), user.PasswordExpirationDate.ToString(), user.SurplusPasswordExpirationDays.ToString());                                 oleDbCommand.ExecuteNonQuery();                             }                         }                     } 復制代碼       還有使用SmtpClient發送郵件的代碼:     復制代碼             using (SmtpClient smtpClient = new SmtpClient())             {                 if (!string.IsNullOrEmpty(mailMessageInfo.Host))                 {                     smtpClient.Host = mailMessageInfo.Host;                 }                 if (!string.IsNullOrEmpty(mailMessageInfo.Port))                 {                     smtpClient.Port = int.Parse(mailMessageInfo.Port);                 }                 smtpClient.Credentials = new System.Net.NetworkCredential();                 if (!string.IsNullOrEmpty(mailMessageInfo.UserName))                 {                     NetworkCredential networkCredential = new NetworkCredential { UserName = mailMessageInfo.UserName };                     if (!string.IsNullOrEmpty(mailMessageInfo.PassWord))                     {                         networkCredential.Password = mailMessageInfo.PassWord;                     }                     smtpClient.Credentials = networkCredential;                 }                 MailMessage mailMessage = new MailMessage();                 if (!string.IsNullOrEmpty(mailMessageInfo.From))                 {                     mailMessage.From = new MailAddress(mailMessageInfo.From);                 }                 foreach (string to in mailMessageInfo.ToList)                 {                     if (!string.IsNullOrWhiteSpace(to))                     {                         mailMessage.To.Add(to);                     }                 }                 if (mailMessageInfo.CcList != null && mailMessageInfo.CcList.Length > 0)                 {                     foreach (string cc in mailMessageInfo.CcList)                     {                         if (!string.IsNullOrWhiteSpace(cc))                         {                             mailMessage.To.Add(cc);                         }                     }                 }                 mailMessage.IsBodyHtml = true;                 string path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "templates", mailMessageInfo.TemplateFileName);                 string body = File.ReadAllText(path);                 Regex regexImg = new Regex(@"<img\s[^>]*>", RegexOptions.IgnoreCase);                 Regex regexSrc = new Regex(                     @"src=(?:(['""])(?<src>(?:(?!\1).)*)\1|(?<src>[^\s>]+))",                     RegexOptions.IgnoreCase | RegexOptions.Singleline);                 MatchCollection matchCollection = regexImg.Matches(body);                 Dictionary<string, string> contentIds = new Dictionary<string, string>();                 foreach (Match matchImg in matchCollection)                 {                     if (regexSrc.IsMatch(matchImg.Groups[0].Value))                     {                         Match matchSrc = regexSrc.Match(matchImg.Groups[0].Value);                         string srcValue = matchSrc.Groups["src"].Value;                         if (!srcValue.StartsWith("http:", System.StringComparison.OrdinalIgnoreCase)                             && !srcValue.StartsWith("file:", System.StringComparison.OrdinalIgnoreCase))                         {                             if (srcValue.IndexOf("/") == 0)                             {                                 srcValue = srcValue.Substring(1);                             }                             string attachmentContentId = Path.GetFileName(srcValue).Replace(".", string.Empty);                             body = body.Replace(matchSrc.Groups["src"].Value, "cid:" + attachmentContentId);                             if (!contentIds.ContainsKey(attachmentContentId))                             {                                 string inlinePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "templates", srcValue.Replace(@"/", @"\"));                                 Attachment inline = new Attachment(inlinePath);                                 inline.ContentDisposition.Inline = true;                                 inline.ContentDisposition.DispositionType = DispositionTypeNames.Inline;                                 inline.ContentId = attachmentContentId;                                 if (srcValue.EndsWith("gif", StringComparison.OrdinalIgnoreCase))                                 {                                     inline.ContentType.MediaType = MediaTypeNames.Image.Gif;                                 }                                 else                                 {                                     inline.ContentType.MediaType = MediaTypeNames.Image.Jpeg;                                 }                                 inline.ContentType.Name = Path.GetFileName(inlinePath);                                 mailMessage.Attachments.Add(inline);                                 contentIds.Add(attachmentContentId, null);                             }                         }                     }                 }                 mailMessage.Body = body; ;                 mailMessage.BodyEncoding = Encoding.UTF8;                 mailMessage.Subject = mailMessageInfo.Subject;                 mailMessage.SubjectEncoding = Encoding.UTF8;                 smtpClient.Send(mailMessage);             }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved