5

Active Directory からユーザーとグループの情報を返す WCF Web サービスを作成しました。ほとんどのグループとユーザーで機能します。

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

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

これまでの私の理論:

  • 一部のセキュリティ制限により、欠落しているグループを照会してそのメンバーを列挙することはできますが、invoke() を介してすべてのグループを列挙することはできません。

  • 呼び出しには、グループの一部のサブセットで問題があります。おそらく、ユニバーサル、動的、または Exchange 対応のプロパティが機能している

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

4

3 に答える 3

7

DirectoryEntry で「Groups」プロパティを使用する場合、次の 2 つの既知の問題があります。

  • ユーザーが属する「デフォルトグループ」(通常は「ユーザー」)は表示されません
  • ネストされたグループ メンバーシップは表示されません

したがって、ユーザーがグループ A のメンバーであり、そのグループがグループ B のメンバーである場合、Windows では、ユーザーがグループ B のメンバーでもあることを意味します。メンバーシップ。

これらは、直接の 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();
}

ネストされたグループを取得するには、いくつかの手順が必要です。それが問題である場合は、その解決策を探す必要があります。

マルク

PS:補足として-なぜ「DirectoryEntry.Invoke("groups", null)」呼び出しを行っているのですか? 多値 (複数の値を含む) で、グループの DN (識別名) を持つ DirectoryEntry.Properties["memberOf"] プロパティを列挙しないのはなぜですか?

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

または、.NET 3.5 を使用している場合は、S.DS.AccountManagement の新しいセキュリティ プリンシパル クラスを利用できます。そのうちの 1 つは「UserPrincipal」であり、「GetAuthorizationGroups()」と呼ばれるメソッドがあり、このすべての面倒な作業を基本的に無料で行います。

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

于 2009-08-12T04:52:51.523 に答える
0

marc_s が正しいと思います。すべてのグループが必要な場合は、次のスニペットを使用できます。

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;
}

ネストされたグループの計算はコストのかかる操作であるため、RefreshCache が完了するまでに時間がかかる場合があることに注意してください。

于 2009-08-12T05:05:47.300 に答える
0

フロイントでは、

私はあなたのコードを利用しようとしていますが、あまりうまくいきません。ディレクトリ エントリ パスを「LDAP://DC=myDomain,DC=co,DC=uk」に更新しましたが、結果が得られません (obj.Properties["tokenGroups"].Count = 0)。

グループをリストするユーザーがどのように指定されているかわかりません。

正しい方向に向けてください。

ありがとう

編集:

やっと整理できました。トークン グループを取得するディレクトリ エントリは、ユーザー エントリである必要があります...それが理にかなっている場合...

他の誰かが同じクエリを持っている場合に備えて、いくつかのコードを含めました。

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
于 2009-08-13T10:37:23.613 に答える