ASP.NET Core – واجهة برمجة تطبيقات ويب تستعلم عن كلمات مرور مستخدم AD التي توشك على انتهاء صلاحيتها

استمرار واجهات برمجة التطبيقات السابقة المتعلقة بكلمة مرور AD,بعد ذلك، تمت كتابة واجهة برمجة تطبيقات يمكنها الاستعلام عن انتهاء صلاحية كلمات مرور مستخدم AD,هذا لن يخوض في التفاصيل حول البيئة,يتم تضمين النماذج、appsettings.json、Program.cs إلخ,لأنه استمرار للمشروع السابق,إذا لزم الأمر ، يمكنك الرجوع إلى المقالة السابقة。


الخدمات/PasswordManagementService.cs

using AD.Models;
using Microsoft.Extensions.Options;
using System.DirectoryServices;
using System.DirectoryServices.Protocols;
using System.Net;
using System.Text;
using System.DirectoryServices.AccountManagement;
using System.Runtime.Versioning;


namespace AD.Services
{
    public class PasswordManagementService(IOptions<LdapSettings> ldapSettings)
    {
        private readonly string _ldapServer = ldapSettings.Value.Server;
        private readonly string _domain = ldapSettings.Value.Domain;
        private readonly string _baseDn = ldapSettings.Value.BaseDn;

        // 查詢網域密碼政策
        [SupportedOSPlatform("windows")] // 宣告以下方法僅適用於 Windows,避免 DirectorySearcher 等 class 被提示要留意跨平臺問題。
        public TimeSpan GetMaxPasswordAge()
        {
            try
            {
                // 使用 DirectorySearcher 查詢網域《群組原則》的「密碼最長使用期限」。
                using DirectorySearcher searcher = new(new DirectoryEntry($"LDAP://{_baseDn}"))
                {
                    Filter = "(objectClass=domain)"
                };
                searcher.PropertiesToLoad.Add("maxPwdAge"); // 密碼最長使用期限

                SearchResult? result = searcher.FindOne();

                if (result != null && result.Properties.Contains("maxPwdAge"))
                {
                    long maxPwdAgeTicks = (long)result.Properties["maxPwdAge"][0]; // 「密碼最長使用期限」原始數值,
                    return TimeSpan.FromTicks(maxPwdAgeTicks); // 轉成 TimeSpan 物件。(TimeSpan 物件在時間處理較為方便)
                }

                return TimeSpan.Zero; // 找不到資料時,回傳 0
            }
            catch (Exception ex)
            {
                Console.WriteLine($"查詢網域密碼政策時,發生錯誤: {ex.Message}");
                return TimeSpan.Zero;
            }
        }

        // 查詢密碼即將到期的使用者
        [SupportedOSPlatform("windows")] // 宣告以下方法僅適用於 Windows,避免 GetMaxPasswordAge() 等方法被提示要留意跨平臺問題。
        public List<String> GetUsersWithExpiringPasswords(int daysUntilExpiry)
        {
            List<String> expiringUsers = []; // 「密碼即將到期的使用者」清單。

            try
            {
                TimeSpan MaxPasswordAge = GetMaxPasswordAge(); // 取得「密碼最長使用期限」。

                if (MaxPasswordAge == TimeSpan.Zero) // 未設定「密碼最長使用期限」。
                    return expiringUsers;

                DateTime today = DateTime.Now;
                DateTime thresholdDate = today.AddDays(daysUntilExpiry); // XX 天 (daysUntilExpiry) 後的「到期日期」。

                // 使用 DirectorySearcher 查詢網域《群組原則》的「密碼最長使用期限」。
                using DirectorySearcher searcher = new(new DirectoryEntry($"LDAP://{_baseDn}"))
                {
                    Filter = "(&(objectCategory=person)(objectClass=user)(pwdLastSet=*)(mail=*))" // 篩選有「上次密碼設定時間」、「Mail」的「使用者」。
                };
                searcher.PropertiesToLoad.Add("sAMAccountName"); // AD 帳號
                searcher.PropertiesToLoad.Add("pwdLastSet");     // 上次密碼設定時間
                searcher.PropertiesToLoad.Add("displayName");    // 顯示名稱
                searcher.PropertiesToLoad.Add("mail");           // 電子郵件

                foreach (SearchResult result in searcher.FindAll())
                {
                    long pwdLastSetTicks = (long)result.Properties["pwdLastSet"][0]; // 使用者帳戶的「上次密碼設定時間」。
                    DateTime pwdLastSet = DateTime.FromFileTime(pwdLastSetTicks);    // 轉成 DateTime 格式。(具體的日期)
                    DateTime passwordExpiryDate = pwdLastSet + MaxPasswordAge;       // 使用者帳戶的「密碼到期日」。

                    if (passwordExpiryDate <= thresholdDate) // 已經到期或未來 XX 天內會到期的帳戶
                    {
                        string userSAMAccountName = result.Properties["sAMAccountName"][0].ToString() ?? string.Empty; // AD 帳號
                        string userPasswordExpiryDate = passwordExpiryDate.ToString("yyyy/MM/dd") ?? string.Empty;     // 上次密碼設定時間
                        string userDisplayName = result.Properties["displayName"][0].ToString() ?? string.Empty;       // 顯示名稱
                        string userMail = result.Properties["mail"][0].ToString() ?? string.Empty;                     // 電子郵件

                        string expiringUsersInfo = $"{userSAMAccountName};{userPasswordExpiryDate};{userDisplayName};{userMail}";
                        expiringUsers.Add(expiringUsersInfo);
                    }
                }

                return expiringUsers; // 若沒結果,回傳空的清單。
            }
            catch (Exception ex)
            {
                Console.WriteLine($"查詢密碼即將到期的使用者時,發生錯誤: {ex.Message}");
                return expiringUsers;
            }
        }
    }
}

 

وحدات التحكم/PasswordManagementController.cs

using AD.Models;
using AD.Services;
using Microsoft.AspNetCore.Mvc;
using System.Runtime.Versioning;

namespace AD.Controllers
{
    [Route("password")]
    [ApiController]

    public class PasswordManagementController(PasswordManagementService passwordManagement) : ControllerBase
    {

        // 取得密碼即將到期的使用者
        [HttpGet("get-expiry-users/{days}")]
        [SupportedOSPlatform("windows")] // 宣告以下用到的方法僅適用於 Windows,避免 GetUsersWithExpiringPasswords 方法被提示要留意跨平臺問題。

        public IActionResult GetExpiringUsers(int days)
        {
            try
            {
                var users = passwordManagement.GetUsersWithExpiringPasswords(days);
                return Ok(new { expiringUsers = users }); // 回傳一個包含 ExpiringUsers 屬性,其值為 users 的 JSON 格式。
            }
            catch (Exception ex) {
                return StatusCode(500, new { Message = "發生錯誤", Error = ex.Message });
            }
        }
    }
}

 

نتائج اختبار Swagger

 

"الروابط ذات الصلة"

اترك التعليق

يرجى ملاحظة: الاعتدال هو مكن تعليق، وربما تؤخر تعليقك. ليست هناك حاجة لإعادة تعليقك.