AD帳戶操作C#範例程式碼(二)——檢查密碼將到期的使用者

來源:互聯網
上載者:User

標籤:blog   http   使用   os   io   檔案   資料   for   

本文接著和大家分享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 bool IsNoPasswordRequired { get; set; }        /// <summary>        /// 系統密碼到期設定天數        /// </summary>        public long MaxPasswordAge { get; set; }        /// <summary>        /// 剩餘到期天數        /// </summary>        public double? SurplusPasswordExpirationDays {            get             {                if (!PasswordExpirationDate.HasValue)                {                    return default(double?);                }                double days = PasswordExpirationDate.Value.Subtract(DateTime.Now).TotalDays;                if (days <= 0)                {                    return 0;                }                return Math.Round(days, 2);             }        }        /// <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))"。注意:表示與或非的“&”、“|”、“!”要放在這些條件運算式前面而不是它們之間;如果要做模糊查詢用萬用字元*;可以用“=”、“>=”、“<=”、“~=”(約等於),但“>”和”<“是不行的;”pwdLastSet“要轉為Windows檔案時間,因為存的是個long,還有處理”userAccountControl"的並運算,這裡用“:1.2.840.113556.1.4.803:=”。我們可以把一些查詢條件放在Filter裡,減少搜尋結果的返回行數:

                    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 (!containsDisabled)                    {                        filterItems.Add(@"(!(userAccountControl:1.2.840.113556.1.4.803:=2))");                    }                    if (!containsPasswordNeverExpire)                    {                        filterItems.Add(@"(!(userAccountControl:1.2.840.113556.1.4.803:=65536))");                    }                    if (!containsNoPasswordRequired)                    {                        filterItems.Add(@"(!(userAccountControl:1.2.840.113556.1.4.803:=32))");                    }                    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));

     Filter文法請參考:http://msdn.microsoft.com/en-us/library/aa746475.aspx、http://www.ldapexplorer.com/en/manual/109010000-ldap-filter-syntax.htm。

     userAccountControl標誌請參考:http://support.microsoft.com/kb/305144/zh-cn、http://msdn.microsoft.com/zh-cn/library/ms680832(VS.85).aspx、http://technet.microsoft.com/library/ee198831.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,剩下貼段將使用者資訊匯出Excel的代碼:

 View Code

      還有使用SmtpClient發送郵件的代碼,可以自訂個HTML檔案做模版內容:

 View Code

 

     最後,將這些代碼整合起來,就是檢查使用者密碼到期的小工具了!由於筆者水平有限,文中難免會有些疏漏和錯誤,代碼也有待不斷最佳化,歡迎各位高手提出寶貴的建議!

參考資料:

DirectoryEntry 類使用 http://msdn.microsoft.com/zh-cn/library/z9cddzaa(v=vs.110).aspx

DirectorySearcher 類使用 http://msdn.microsoft.com/zh-cn/library/System.DirectoryServices.DirectorySearcher(v=vs.90).aspx

輕量目錄訪問協議 (LDAP) http://msdn.microsoft.com/en-us/library/aa367008(VS.85).aspx

檢查密碼將到期使用者小工具:http://files.cnblogs.com/CSharpDevelopers/UserPasswordSetChecker.zip

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.