2011-05-18 64 views
3

我有一個客戶端服務解決方案,其中包含一個Winforms客戶端應用程序和一個WCF服務,託管在IIS中。如何從Active Directory獲取正確的數據進行身份驗證

在WCF服務中,我可以使用自定義IAuthorizationPolicy輕鬆提取客戶端上登錄的當前用戶的名稱(WindowsIdentity.Name)。這是通過在Evaluate方法中獲取來自EvaluationContextWindowsIdentity來完成的。

WindowsIdentity.Name會是這個樣子:MyCompanyGroup\MyName

爲了能夠綁定到AD帳戶,在我自己的會員制模式,我需要能夠讓用戶選擇的AD用戶綁定到上的WinForms客戶。爲了提取AD組和用戶的一棵樹,我用下面的代碼:

public static class ActiveDirectoryHandler 
{ 
    public static List<ActiveDirectoryTreeNode> GetGroups() 
    { 
    DirectoryEntry objADAM = default(DirectoryEntry); 
    // Binding object. 
    DirectoryEntry objGroupEntry = default(DirectoryEntry); 
    // Group Results. 
    DirectorySearcher objSearchADAM = default(DirectorySearcher); 
    // Search object. 
    SearchResultCollection objSearchResults = default(SearchResultCollection); 
    // Results collection. 
    string strPath = null; 
    // Binding path. 
    List<ActiveDirectoryTreeNode> result = new List<ActiveDirectoryTreeNode>(); 

    // Construct the binding string. 
    strPath = "LDAP://stefanserver.stefannet.local"; 
    //Change to your ADserver 

    // Get the AD LDS object. 
    try 
    { 
     objADAM = new DirectoryEntry();//strPath); 
     objADAM.RefreshCache(); 
    } 
    catch (Exception e) 
    { 
     throw e; 
    } 

    // Get search object, specify filter and scope, 
    // perform search. 
    try 
    { 
     objSearchADAM = new DirectorySearcher(objADAM); 
     objSearchADAM.Filter = "(&(objectClass=group))"; 
     objSearchADAM.SearchScope = SearchScope.Subtree; 
     objSearchResults = objSearchADAM.FindAll(); 
    } 
    catch (Exception e) 
    { 
     throw e; 
    } 

    // Enumerate groups 
    try 
    { 
     if (objSearchResults.Count != 0) 
     { 
      //SearchResult objResult = default(SearchResult); 
      foreach (SearchResult objResult in objSearchResults) 
      { 
       objGroupEntry = objResult.GetDirectoryEntry(); 
       result.Add(new ActiveDirectoryTreeNode() { Id = objGroupEntry.Guid, ParentId = objGroupEntry.Parent.Guid, Text = objGroupEntry.Name, Type = ActiveDirectoryType.Group, PickableNode = false }); 

       foreach (object child in objGroupEntry.Properties["member"]) 
        result.Add(new ActiveDirectoryTreeNode() { Id= Guid.NewGuid(), ParentId = objGroupEntry.Guid, Text = child.ToString(), Type = ActiveDirectoryType.User, PickableNode = true }); 
      } 
     } 
     else 
     { 
      throw new Exception("No groups found"); 
     } 
    } 
    catch (Exception e) 
    { 
     throw new Exception(e.Message); 
    } 

    return result; 
    } 
} 

public class ActiveDirectoryTreeNode : ISearchable 
{ 
    private Boolean _pickableNode = false; 
#region Properties 
[GenericTreeColumn(GenericTableDescriptionAttribute.MemberTypeEnum.TextBox, 0, VisibleInListMode = false, Editable = false)] 
public Guid Id { get; set; } 
[GenericTreeColumn(GenericTableDescriptionAttribute.MemberTypeEnum.TextBox, 1, VisibleInListMode = false, Editable = false)] 
public Guid ParentId { get; set; } 
[GenericTreeColumn(GenericTableDescriptionAttribute.MemberTypeEnum.TextBox, 2, Editable = false)] 
public string Text { get; set; } 
public ActiveDirectoryType Type { get; set; } 
#endregion 

#region ISearchable 
public string SearchString 
{ 
    get { return Text.ToLower(); } 
} 

public bool PickableNode 
{ 
    get { return _pickableNode; } 
    set { _pickableNode = value; } 
} 
#endregion 

} 

public enum ActiveDirectoryType 
{ 
    Group, 
    User 
} 

樹可能是這個樣子:

CN=Users* 
- CN=Domain Guests,CN=Users,DC=MyCompany,DC=local 
- CN=5-1-5-11,CN=ForeignSecurityPrinipals,DC=MyCompany,DC=local 
... 
CN=Domain Admins 
- CN=MyName,CN=Users,DC=MyCompany,DC=local 
... 

(* =集團)

名稱是不同的格式,我不明白這可以與服務的名稱相比。

那麼如何提取適當的Active Directory數據的樹?

回答

1

我不能聲稱明白你在問什麼,但這裏有一些信息,我希望你能找到幫助。

您在服務中看到的名稱(即「MyName」)對應於AD中名爲sAMAccountName的屬性。您可以通過Properties集合從DirectoryEntry中獲取sAMAccountName。例如,如果你想顯示sAMAccountName你組的每個成員,你可以做到以下幾點:

var objSearchADAM = new DirectorySearcher(); 
objSearchADAM.Filter = "(&(objectClass=group))"; 
objSearchADAM.SearchScope = SearchScope.Subtree; 
var objSearchResults = objSearchADAM.FindAll(); 

foreach (SearchResult objResult in objSearchResults) 
{ 
    using (var objGroupEntry = objResult.GetDirectoryEntry()) 
    { 
     foreach (string child in objGroupEntry.Properties["member"]) 
     { 
      var path = "LDAP://" + child.Replace("/", "\\/"); 
      using (var memberEntry = new DirectoryEntry(path)) 
      { 
       if (memberEntry.Properties.Contains("sAMAccountName")) 
       { 
        // Get sAMAccountName 
        string sAMAccountName = memberEntry.Properties["sAMAccountName"][0].ToString(); 
        Console.WriteLine(sAMAccountName); 
       } 

       if (memberEntry.Properties.Contains("objectSid")) 
       { 
        // Get objectSid 
        byte[] sidBytes = (byte[]) memberEntry.Properties["objectSid"][0]; 
        var sid = new System.Security.Principal.SecurityIdentifier(sidBytes, 0); 
        Console.WriteLine(sid.ToString()); 
       } 
      } 
     } 
    } 
} 

您也可能會發現UserPrincipal有趣。有了這個類可以非常方便的連接到用戶對象在AD與FindByIdentity方法如下所示:

var ctx = new PrincipalContext(ContextType.Domain, null); 
using (var up = UserPrincipal.FindByIdentity(ctx, IdentityType.SamAccountName, "MyName")) 
{ 
    Console.WriteLine(up.DistinguishedName); 
    Console.WriteLine(up.SamAccountName); 

    // Print groups that this user is a member of 
    foreach (var group in up.GetGroups()) 
    { 
     Console.WriteLine(group.SamAccountName); 
    } 
} 
+0

謝謝!但是,第一個代碼在嘗試創建DirectoryEntry對象時給了我一個明確的提示:爲adsObject提供的值不會實現IAD? – Banshee 2011-05-19 06:28:48

+0

我改變了child.ToString(),然後我得到了我的drectoryEntry對象,但當我試圖獲取sAMAccountName時,我得到了類型'System.Runtim.InteropService.ComException'的異常? – Banshee 2011-05-19 07:23:30

+0

對不起,我在我的代碼中犯了一個錯誤。我忘了將「LDAP://」添加到成員路徑中。我更新了我的答案,請嘗試更新示例代碼。 – 2011-05-19 08:24:47

相關問題