本文說明如何使用原生 Active Directory 服務介面 (ADSI) 元件來判斷使用者的主要群組成員資格。
主要群組在 Active Directory 使用者物件上的儲存方式
安全性內容中的每個物件 (例如使用者和安全性群組) Active Directory 有與其相關聯的安全性識別元 (SID) 屬性。SID 元件參考包含在本文 < 參考 > 一節所述,SID 會有數個元件。兩個 SID 上這些元件是網域相關識別元 (RID)] 和 [RID 特定網域內的物件。
使用者主要群組儲存為 (使用者的網域中的群組的 RID)
PrimaryGroupID 屬性的使用者物件上。使用者的主要群組僅能存在於相同之使用者的網域中的群組,而且此群組必須是群組的使用者所屬的成員。而且,在 Active Directory 中的這個
群組 物件有稱為
PrimaryGroupToken,儲存此群組在網域內 RID 它的屬性。
Windows NT 和輕量型目錄存取通訊協定 (LDAP) 提供者可讓程式設計人員
PrimaryGroupID 屬性值設定為使用者所隸屬的群組的 RID 變更使用者的主要群組。如果使用者不是群組的成員,使用者的
PrimaryGroupID 不能設定群組的 RID 中。
當它會使用 Windows NT 提供者 ADSI 中時,主要群組是以使用者的
IADsUser::Groups 集合中的項目,包括。
與 LDAP] 提供者主要群組是
不 包括作為
IADsUser::Groups] 集合中的項目,也不是群組的辨別名稱 (DN) 一部分的目錄中的使用者物件
隸屬 屬性。群組的 RID
PrimaryGroupID 中是唯一的地方 LDAP 使用者物件已參考主要群組的使用者。
兩者都不提供者定義機制來判斷直接從其各自的使用者物件的使用者主要群組名稱。問題是由每個提供者所提供的每個群組物件,如下所示支援一組不同的屬性,事實進行更為複雜:
- 提供 Windows NT 群組物件不支援 PrimaryGroupToken] 屬性,也會執行 Windows NT 提供者支援任何其他方法可以使用 ADSI 的原生程式碼來擷取群組的 RID。
- LDAP 提供者群組物件的 PrimaryGroupToken 屬性是計算的屬性。這個屬性不存在於目錄中的 [群組] 物件上。使用 IADs::GetInfoEx 方法呼叫用戶端要求時,就,在實際上會建立屬性。 您不可能執行根據 Active Directory 中的建構屬性的 LDAP 搜尋。因此,您無法搜尋藉由使用 LDAP 提供者的群組,根據 PrimaryGroupToken 屬性符合您想要決定其主要群組的使用者物件上的 [PrimaryGroupID] 屬性。這也規則出純粹的 ADSI 方案不是依賴外部 COM 物件,幫助您判斷主要群組。
判斷使用者主要群組的方式
以下是三種已知的方法來判斷使用者的主要群組的名稱:
- 建置一個 SID 群組物件從網域 RID 的元件使用者的 SID 和群組的 RID 儲存在使用者物件上 PrimaryGroupID 屬性上的 [動態目錄] 中的繫結字串。
這是 Microsoft 知識庫文件 Q297951 (包含在本文 < 參考 > 一節) 中所述的方法。這個方法主要的問題就是若要建置 SID 繫結字串,程式設計人員必須依賴 ADsSID 物件,將網域物件的二進位的安全性描述元轉換成它 SDDL 的表單。ADsSID 物件是由 ADsSecurity.dll 檔案必須複製到並登錄在用戶端程式碼可以順利執行之前,先裝載。 - 使用 LDAP 查詢來搜尋網域中的所有群組並傳回其 PrimaryGroupToken 屬性。
這個方法會是純粹的 LDAP 方案。不過,指令碼式的解決方案不非常有效率,因為這個搜尋會傳回每個群組在網域甚至那些使用者不是; 的成員,並且因為 PrimaryGroupToken 屬性建構在用戶端,如周遊資料錄集,這個搜尋是相當緩慢。這個方法可能非常特別耗時如果有大量的網域中的群組。 如何建立 LDAP 方言 ADO 查詢的範例 abound,而且因此,它們不包含在這篇文章。 - 利用下建置混合式解決方案的每個提供者功能。
這個方案會利用不同的提供者,以判斷該使用者的主群組功能。要這麼做,請您執行下列步驟:- 繫結至使用者物件,與 Windows NT 提供者。
Windows NT 使用者物件提供保證包含使用者的主要群組的群組集合。而且,PrimaryGroupID 的使用者物件也會立即儲存在暫存的位置以供稍後在這個演算法中使用。 - 列舉 IADsUser::Groups 集合。
- 從這個集合中每個群組的 ADsPath 解壓縮 SamAccountName 屬性,然後再建置要搜尋的所有群組與此集合傳回其 PrimaryGroupToken 和 DistinguishedName] 屬性值中所列的 SamAccountName 屬性的 LDAP 方言查詢字串。
- 執行 ADO ADSI 的搜尋,並再執行迴圈記錄集比較每個群組 PrimaryGroupToken 以快取稍早的 PrimaryGroupID 屬性值。
- 如果找到相符項目,停止並顯示此群組的辨別名稱為此使用者的主要群組。
- 如果沒有找到相符的項目繼續搜尋結果中執行迴圈。
這個方法的優點是立即明顯。所有用的物件是 ADSI 以原生並不需要額外的元件。此外,列舉型別包括可能是主要群組這些群組。
不過,請注意下列缺點: 當列舉 IADsUser::Groups 集合傳回物件是 IADs 介面成員在群組中。如果基於某些原因執行列舉型別使用者沒有所需的權限開啟特定的物件,列舉型別會停止沒有指出錯誤。下列程式碼將說明您可以如何來實作前述的演算法:
dim oUsr
dim oGrp
'
' ToDo: Change the following variables to specific values for your domain.
'
DomainName = "myDomain"
UserLoginName = "myUserLoginName"
'
' Bind to the user object with the Windows NT provider.
'
set oUsr = GetObject("WinNT://" & DomainName & "/" & UserLoginName & ",user")
set grp = oUsr.Groups
GrpID = oUsr.PrimaryGroupID
GrpName = ""
'
' Building Query Filter for the search for all the groups that the user is a member of.
'
QueryFilter = "(|"
for each Item in Grp
NT4Name = replace(Item.ADsPath,"WinNT://","")
tempArray = split(nt4Name,"/")
NT4Name = tempArray(1)
QueryFilter = QueryFilter & "(samAccountName=" & NT4Name & ")"
next
QueryFilter = QueryFilter & ")"
'
' Building LDAP dialect Query String.
'
QueryString = "<LDAP://" & DomainName & ">;" & QueryFilter & ";PrimaryGroupToken,distinguishedName;subtree"
'
' Performing Query against the Active Directory for all the groups that
' the user belongs to and retrieving the RID of the group object off
' the PrimaryGroupToken attribute on the user.
'
Dim oConnection, oCommand, oRecordset
Set oConnection = CreateObject("ADODB.Connection")
Set oCommand = CreateObject("ADODB.Command")
oConnection.Provider = "ADsDSOObject"
oConnection.Open "Active Directory Provider"
Set oCommand.ActiveConnection = oConnection
oCommand.CommandText = QueryString
oCommand.Properties("Page Size") = 900
Set oRecordset = oCommand.Execute
'
' Looping through all the records in the search result to determine whether
' any of these group's PrimaryGroupToken attribute value match the
' PrimaryGroupID attribute value stored on the user object.
'
While ((NOT oRecordset.EOF) and (Not bGroupFound))
if (GrpID = oRecordset.Fields("PrimaryGroupToken").value) then
GrpName = oRecordset.Fields("DistinguishedName").Value
bGroupFound = True
End If
oRecordset.moveNext
Wend
Set oRecordset = Nothing
Set oCommand = Nothing
Set oConnection = Nothing
'
' Displaying Results of the search.
'
if( bGroupFound ) then
WScript.Echo "Primary Group for " & oUsr.AdsPath
WScript.Echo "Is: " & GrpName
else
WScript.Echo "Primary Group Not Found"
end if
如需詳細資訊,請按一下下列的文件編號,檢視 「 Microsoft 知識庫 」 中的文件:
297951?
(http://support.microsoft.com/kb/297951/
)
如何使用 PrimaryGroupID 屬性來尋找使用者的主要群組