核心概念速查
| 術語 | 全名 | 說明 |
| ADsPath | Active Directory Service Path | 物件唯一路徑,格式 LDAP://DC=domain,DC=com 或 LDAP://Server/DC=domain,DC=com |
| DN | Distinguished Name | 完整唯一名稱,如 CN=Admin,CN=Users,DC=domain,DC=com |
| RDN | Relative Distinguished Name | 相對父容器的名稱,如 CN=Admin |
| CN | Common Name | 通用名稱 (使用者、群組、電腦等) |
| OU | Organizational Unit | 組織單元 (容器),可委派管理權限 |
| DC | Domain Component | 網域元件 (DNS 網域名稱拆解) |
| GUID | Globally Unique Identifier | 物件不變的唯一識別碼 (跨網域移動不變) |
| SID | Security Identifier | 安全性主體識別碼 (權限核心) |
三大命名內容 (Naming Contexts)
- Domain NC:
DC=domain,DC=com - 使用者、群組、電腦、OU 等業務資料。
- Configuration NC:
CN=Configuration,DC=domain,DC=com - 網站、子網、複寫拓撲、信任關係等基礎建設設定。
- Schema NC:
CN=Schema,CN=Configuration,DC=domain,DC=com - 類別與屬性定義 (可擴充)。
System.DirectoryServices 核心類別
DirectoryEntry - 物件操作
using System.DirectoryServices;
// 綁定 (支援指定認證)
var entry = new DirectoryEntry("LDAP://DC=domain,DC=com", "user", "pwd", AuthenticationTypes.Secure);
// 常用操作
entry.Properties["description"].Value = "更新說明";
entry.CommitChanges(); // 寫回 AD
// 建立子物件
var newUser = entry.Children.Add("CN=NewUser", "user");
newUser.Properties["sAMAccountName"].Value = "newuser";
newUser.CommitChanges();
// 移動/重命名
newUser.MoveTo(new DirectoryEntry("LDAP://OU=TargetOU,DC=domain,DC=com"));
// 列舉子物件
foreach (DirectoryEntry child in entry.Children) {
Console.WriteLine($"{child.Name} - {child.SchemaClassName}");
}
// 多值屬性處理 (如 memberOf)
foreach (object val in entry.Properties["memberOf"])
Console.WriteLine(val);
DirectorySearcher - 高效查詢
var searcher = new DirectorySearcher(entry) {
Filter = "(&(objectCategory=person)(objectClass=user)(mail=*@domain.com))",
SearchScope = SearchScope.Subtree,
PageSize = 1000, // 啟用分頁,繞過伺服器 MaxPageSize 限制
PropertiesToLoad = { "cn", "mail", "department", "manager" }
};
// 異步查詢大量資料
foreach (SearchResult result in searcher.FindAll()) {
var de = result.GetDirectoryEntry(); // 取得 DirectoryEntry (會再發一次 RPC)
// 建議直接用 result.Properties 讀取已載入屬性,避免額外往返
string mail = (string)result.Properties["mail"][0];
}
SearchScope 三種模式圖解
- Base:僅查詢 SearchRoot 本身。
- OneLevel:查詢 SearchRoot 直系子物件 (不含孫輩)。
- Subtree:查詢 SearchRoot 及所有後代 (預設、最常用)。
SQL Server 連結伺服器查詢 AD (OpenQuery)
-- 建立連結伺服器 (一次)
EXEC sp_addlinkedserver 'ADSI', 'Active Directory Service Interfaces', 'ADSDSOObject', 'adsdatasource';
-- 查詢範例
SELECT displayName, mail, telephoneNumber, sAMAccountName
FROM OPENQUERY(ADSI, '
SELECT displayName, mail, telephoneNumber, sAMAccountName
FROM ''LDAP://DC=domain,DC=com''
WHERE objectClass = ''user'' AND objectCategory = ''person''
')
WHERE mail LIKE '%@domain.com';
ADAM (Active Directory Application Mode) 快速認知
- 輕量級 LDAP 目錄服務,獨立於作業系統網域,無需 DNS、無網域控制站角色。
- 單機可跑多個 Instance (每個 App 一個),以使用者模式服務運行 (非系統服務)。
- 適用場景:應用程式專用目錄、Extranet 身分存放、開發測試環境。
- .NET 操作方式同 AD,僅綁定路徑改為
LDAP://localhost:389/CN=Partition,CN=Schema,CN=Configuration 等。
效能調優關鍵清單
- **指定 PropertiesToLoad** 只取需要屬性,減少網路傳輸。
- **設定 PageSize** (如 1000) 啟用分頁,避免單次回傳過大被截斷。
- **使用索引屬性查詢** (如 `sAMAccountName`, `objectGUID`, `mail`),避免全樹掃描。
- **重用 DirectoryEntry/Searcher** 物件,減少綁定開銷。
- **批次修改** 使用 `DirectoryAttributeModification` 合併多屬性一次 Commit。
- **GC (Global Catalog) 查詢** 跨網域搜尋時連接 GC Port 3268,單一查詢覆蓋整個林。