2009-08-12 29 views
4

Active Directoryからユーザーとグループの情報を返すWCF Webサービスを作成しました。これは、ほとんどのグループとユーザーに有効です。DirectoryEntry.Invoke( "groups"、null)すべてのグループを取得しませんか?

私はdirectoryEntry.Invoke( "groups"、null)を使用して、指定されたユーザーがメンバーであるグループを返します。これはMOSTグループを返します。奇妙なことは、メンバーの1つで呼び出しクエリを使用したときにグループが見つからなくても、グループを見つけてそのメンバーを列挙できることです。

この現象を示すグループのほとんどはExchange対応です。問題の多いユーザーアカウントのほとんどは、フェデレーションドメイン内のユーザーで、クエリを実行するドメイン内のExchangeサーバーを使用しています。私はフェデレーションドメインのオブジェクトを照会しようとしていません。

これまでの私の理論:

  • いくつかのセキュリティ上の制限は、私が不足しているグループを照会し、そのメンバーを列挙することができるにもかかわらず)(呼び出しを経由してすべてのグループを列挙することはできません。

  • invokeはグループの一部のサブセットに問題があります。

  • 「フェデレーションされた」アカウント(Exchangeアカウント設定の一部として作成された)が通常のドメインアカウントとは何らかの形で異なるため、呼び出しメソッドがすべてのグループを選択しない可能性があります。 sidを超えてログインドメインにマッピングされます。

答えて

5

のDirectoryEntryの「グループ」プロパティを使用して、2つの既知の問題があります。

  • それはあなたのユーザーは、(一般的に「ユーザー」)にある「既定のグループ」を表示されません
  • ユーザーがグループAのメンバーであり、そのグループはその後、今度はグループBのメンバーである場合
  • 、それはあなたのネストされたグループが表示されませんが

だから、メンバーシップ、そしてWindowsで、これはユーザーでもあることを意味しメンバーただし、DirectoryEntryはネストされたグループメンバシップを表示しません。

これは、私がストレートActive Directory(Exchangeなし)について知っている2つの唯一の制限です。

デフォルトグループの取得には少し時間がかかりますが、そのためのコードサンプルがあります。ネストされたグループを取得

private string GetPrimaryGroup(DirectoryEntry aEntry, DirectoryEntry aDomainEntry) 
{ 
    int primaryGroupID = (int)aEntry.Properties["primaryGroupID"].Value; 
    byte[] objectSid = (byte[])aEntry.Properties["objectSid"].Value; 

    StringBuilder escapedGroupSid = new StringBuilder(); 

    // Copy over everything but the last four bytes(sub-authority) 
    // Doing so gives us the RID of the domain 
    for(uint i = 0; i < objectSid.Length - 4; i++) 
    { 
     escapedGroupSid.AppendFormat("\\{0:x2}", objectSid[i]); 
    } 

    //Add the primaryGroupID to the escape string to build the SID of the primaryGroup 
    for(uint i = 0; i < 4; i++) 
    { 
     escapedGroupSid.AppendFormat("\\{0:x2}", (primaryGroupID & 0xFF)); 
     primaryGroupID >>= 8; 
    } 

    //Search the directory for a group with this SID 
    DirectorySearcher searcher = new DirectorySearcher(); 
    if(aDomainEntry != null) 
    { 
     searcher.SearchRoot = aDomainEntry; 
    } 

    searcher.Filter = "(&(objectCategory=Group)(objectSID=" + escapedGroupSid.ToString() + "))"; 
    searcher.PropertiesToLoad.Add("distinguishedName"); 

    return searcher.FindOne().Properties["distinguishedName"][0].ToString(); 
} 

もいくつかの手順を取り、私はそれが問題だ場合、その1つの解決策を捜す必要があります。

マルク・

PS:サイドノートとして - なぜ地球上であなたは "DirectoryEntry.Invoke行っている(" グループ "は、null)" と呼んで?なぜ複数値(複数の値を含む)で、グループのDN(識別名)を持つDirectoryEntry.Properties ["memberOf"]プロパティを列挙しないのですか?

foreach(string groupDN in myUser.Properties["memberOf"]) 
{ 
    string groupName = groupDN; 
} 

.NET 3.5の場合は、新しいセキュリティプリンシパルクラスをS.DS.AccountManagementで使用できます。そのうちの1つは "UserPrincipal"です。このメソッドは "GetAuthorizationGroups()"というメソッドを持っています。

優れたMSDN articleを参照してください。これらの新しい.NET 3.5 S.DSの機能について説明しています。

+0

これらを良い提案であり、あなたはMSDNの記事について正しいです、私は開始する前にそれを読んでいたはずです。私がなぜinvokeメソッドを使用したかについては、この例では必要なのはグループ名だけでしたが、これは情報を取得する効率的な方法のようでした。私はActive Directoryに対して非常に多くのプログラミングを行っていないので、進歩するための最善の方法を学んでいます。 1.1以降、この分野で.NETがどの程度進化したのか興味深い! – HeathenWorld

+0

何も問題はありません。Invoke()アプローチを使用する特別な理由があったのかどうか不思議です。そして、ちょっと - それはStackOverflowのすべてです - ツリーのためにフォレストが表示されないときにあなたを助けます:-) –

+0

リンクされたMSDN記事の+1、はるかに容易に3.5 – tbone

0

私はmarc_sが正しいと思います。 RefreshCacheが完了するまでに長い時間がかかる場合がありますので、ネストされたグループを計算することは高価な操作であることを

using (DirectoryEntry obj = new DirectoryEntry("LDAP://" + dn)) 
{ 
    obj.RefreshCache(new string[] { "tokenGroups" }); 
    string[] sids = new string[obj.Properties["tokenGroups"].Count]; 
    int i = 0; 
    foreach (byte[] bytes in obj.Properties["tokenGroups"]) 
    { 
     sids[i] = _ConvertSidToString(bytes); 
     ++i; 
    } 
    obj.Close(); 
    return sids; 
} 

注:すべてのグループが必要な場合は、次のコードを使用することができます。フロイント、

0

私はあなたのコードの使用をしようと非常に遠くなっていません。 "LDAP:// DC = myDomain、DC = co、DC = uk"になるようにディレクトリエントリパスを更新しましたが、結果は表示されません(count = 0)。

私はグループをリストするユーザーをどのように指定するかわからない。

私に正しい方向を教えてください。

おかげ

EDIT:

私はそれが最後にソートました。それは理にかなっている場合...ユーザーエントリでなければなりませんからトークングループを取得するためのディレクトリエントリ...

私は場合は、いくつかのコードを他の誰が同じクエリを持っている含まれている:

Dim directoryEntry As DirectoryEntry = _ 
     New DirectoryEntry("LDAP://CN=users,DC=domanName,DC=com") 
Dim directorySearcher As DirectorySearcher = _ 
     New DirectorySearcher(directoryEntry, "(sAMAccountName=" & UserName & ")") 
Dim searchResult As SearchResult = directorySearcher.FindOne() 

If Not searchResult Is Nothing Then 
    Dim userDirectoryEntry As DirectoryEntry = searchResult.GetDirectoryEntry 
    userDirectoryEntry.RefreshCache(New String() {"tokenGroups"}) 
    ... etc ... 
End If 
関連する問題