使用 NET.Core 進行 LDAP 物件屬性驗證

情境說明

從我開始寫程式以來,LDAP 這項技術就一直存在,但對於缺乏 Infrastructure 背景的我來說,過往的知識都僅侷限在使用程式進行 Active Directory(AD)驗證,如 DN、CN、OU、DC 等相關術語,老實說我從未真正深入了解過(有點心虛)。

最近開發一個小需求,需要驗證使用者輸入的郵件是否存在的功能,在開發過程中出現了一個奇怪的現象:只要透過程式登入,外部網路就會斷線。經過 Infra 部門的查詢,他們發現防火牆(PA)的設定導致了這個問題。公司的政策限制了部分帳號的對外網路存取權限,但這次的問題是,程式綁定了一組可以查詢 AD 資料的帳號後,防火牆政策誤判我的開發機使用的是那一組沒有對外網路存取權限的帳號,因而封鎖了對外網路的存取權限。

這對開發人員來說,造成了一些困擾,因為每次都需要關閉所有開發工具,並登出重新登入,因此也趁此次機會,我決定在虛擬機(VM)上認真地建立一個AD,以滿足我的開發需求,同時也趁這個機會深入了解 LDAP 的運作原理。


LDAP 簡介

在開始之前,還是得先簡單的了解一下何謂 LDAP,它是一個輕量級目錄存取協定,英文全名,(Lightweight Directory Access Protocol),你可以想像它是類似於通訊錄的協定,用於定義組織結構、電腦、以及員工基本資訊等內容,此外,LDAP還可用於進行權限的驗證。

在微軟的生態系統中,有一個廣為人知,基於 LDAP 協定實作的產品,稱為 Active Directory,通常簡寫為AD,它是一個用於管理組織內的資源、提供身份認證服務的目錄服務,並且支援 LDAP 協定,使得組織能夠有效地組織、存取和管理其資源。

而 LDAP 目錄結構主要由底下幾個重要項目所組成

  • DN,Distinguished Name:識別名稱,一筆記錄的完整位置,ex. 【CN=沈小凱,OU=資訊處,OU=高雄,OU=_Taiwan,DC=pex,DC=com】。
  • CN,Common Name:用戶或單位名稱,一筆記錄的名字。
  • OU,Organizational Unit:組織單位名稱,一筆記錄所屬組織。
  • DC,Domain Componet:網域元件,一筆記錄所屬區域。


AD 架設流程

AD 測試環境為 Server 2019,網路上有很多設定的教學步驟,詳細也可以參考這篇的教學,寫的蠻清楚的,這裡我就僅列出幾個重要的步驟。

  1. 因為不確定 AD Server 架設完成後,後續再修改電腦名稱會不會衍伸其它問題,因此建議在安裝前先將伺服器的名稱修改好。
  2. 開啟伺服器管理員 -> 管理 -> 新增角色及功能,選擇 Active Directory 網域服務。
  3. 部署設定,選擇新增樹系,並輸入根網域名稱,請注意這邊輸入的必須為 <主網域>.<頂級網域> 的格式,例如 pex.com,否則會跳出錯誤訊息(如下圖)。
  4. 網域控制站選項,這邊我沒有亂動,就選擇預設值並輸入密碼而已。
  5. DNS 選項,這邊我還不清楚目的是什麼,之後再來研究,直接往下一步進行。
  6. 其它選項,輸入 NetBIOS 網域名稱,我這邊輸入的是 PEX,這裡也就是我們一般 AD 登入的時後左邊的那串名稱,例如 PEX\帳號。

  7. 接下來就按照檢查設定去調整即可完成網域的安裝。

AD 管理工具

安裝好 AD 並重新開機後,應該可以找到【Active Directory 使用者和電腦】這個管理工具,透過此工具可以很快速的查看、新增、編輯、刪除我們的 AD 組織,這邊大概紀錄一下幾個常用的步驟。

管理公司的組織結構和員工資料

如果想要新增組織節點,可以透過滑鼠右鍵的操作來執行,當你右鍵點擊組織節點時,會彈出一個選單,讓你可以選擇新增組織單位、使用者、電腦等。這樣的功能讓你可以方便地在工具中建立公司的組織圖和員工資料。

舉例來說,假設你想要新增一個新的組織單位,你只需要右鍵點擊適當的位置,然後選擇新增組織單位。接著,系統會要求你輸入該組織單位的名稱和其他相關資訊。完成後,新的組織節點就會出現在你的組織圖中。

同樣的道理,如果你需要新增一個新的使用者或電腦,只需選擇相應的選項,然後按照系統提示輸入相關資訊即可。

這樣的功能讓你可以輕鬆管理公司的組織結構和員工資料,並且能夠直觀地在工具中呈現這些資訊。

開啟管理工具進階功能

在對 DN 結構不熟悉時,應該會希望有一個功能可以查看目前組織或使用者等相關資料的 DN 路徑。一開始,我以為工具沒有提供此功能,認為必須自己一層一層串起完整的路徑。後來經過神一般的 Infra 同事指點,其實只要開啟進階功能,就可以輕鬆地查看 DN 路徑,如下圖所示。

下圖是開啟進階功能才會出現物件頁籤,在這裡就可以看到 DN 的路徑,只要搭配本文上方的 LDAP 說明,應該可以輕易地組出 DN 的完整路徑為,CN=沈小凱,OU=資訊處,OU=高雄,OU=_Taiwan,DC=pex,DC=com。

另外一個屬性編輯器的頁籤,這邊也很重要,底下我會分享一個查詢工具,會用到這邊的屬性名稱,以下圖為例,我希望能找到屬性為 mail,並且值為 lawrence_shen@pex.com 的資料。

AD 屬性驗證小工具

下圖是配合本此學習過程中開發的小工具,可以透過此工具來查詢組織 AD 中某些欄位是否存在,例如本文一開始提到的需求,我希望可以驗證各部門的共用電子郵件是否存在,底下是各參數設定的說明。

  • LDAP Host : AD Server 的 IP。
  • LDAP Port : AD Server 的 Port,預設為 389。
  • AD Admin 帳號密碼 : 這組帳號的設定必須要可以讀取 AD 的組織權限,否則會無法查詢。
  • 要查詢的 DN 根路徑 : 沒意外的話,設定網域的 DN 即可,會由此根路徑往下搜尋,但若有多個組織,則指定要搜尋組織的根路徑。
  • 要查詢的屬性 : 就剛剛上面提到的,我的例子是要查詢 mail 欄位,你可以根據你的需求進行調整。
  • 要查詢的值 : 查詢條件。
  • 查詢結果 : 若要符合查詢條件的 email,則會在底下列出該物件的所有屬性。


執行流程的程式範例如下參考。

using (LdapConnection ldapConn = new LdapConnection())
{
	// 連接 AD Server
	ldapConn.Connect(host, port);  
	
	// 綁定查詢帳號
	ldapConn.Bind(adminAccount, adminPassword);

	// 查詢屬性
	string searchFilter = $"({propertyName}={propertyValue})";
	var searchResults = ldapConn.Search(
		searchBaseDn,
		LdapConnection.ScopeSub,
		searchFilter,
		null, 
		false  
	);

	if (searchResults.HasMore())
	{
		// 取得物件屬性
		var nextEntry = searchResults.Next();
	}

	ldapConn.Disconnect();
}


本文範例下載 : Github,使用 NetCore 8。

留言