ネイティブな ADSI コンポーネントを使用してプライマリ グループを取得する方法

文書翻訳 文書翻訳
文書番号: 321360 - 対象製品
この記事は、以前は次の ID で公開されていました: JP321360
すべて展開する | すべて折りたたむ

目次

概要

この資料では、Active Directory Services Interface (ADSI) コンポーネントを使用して、ユーザーのプライマリ グループ メンバシップを判別する方法について説明します。

詳細

プライマリ グループはどのように Active Directory 内のユーザー オブジェクトに格納されているか

Active Directory 内のすべてのセキュリティ コンテキスト オブジェクト (ユーザーやセキュリティ グループなど) には、セキュリティ識別子 (SID) 属性が関連付けられています。SID には、この資料の「関連情報」に記載した「SID Components」で説明されているように、いくつかのコンポーネントが含まれます。これら SID のコンポーネントの内の 2 つは、ドメイン相対識別子 (RID) とドメイン内のオブジェクトに固有の RID です。

ユーザーのプライマリ グループは、ユーザー オブジェクトの PrimaryGroupID 属性に (ユーザーが参加しているドメイン内でのグループの RID として) 格納されます。ユーザーのプライマリ グループは、必ず、ユーザーと同じドメイン内に存在し、ユーザーが所属しているグループになります。また、Active Directory 内のこの Group オブジェクトには、PrimaryGroupToken という属性もあります。この属性には、ドメイン内でのプライマリ グループの RID が格納されます。

Windows NT および LDAP (Lightweight Directory Access Protocol) プロバイダでは、プログラマがユーザーのプライマリ グループを変更できるようになっています。これは、PrimaryGroupID 属性の値を、ユーザーが所属しているグループの RID に設定することによって行います。ユーザーがグループのメンバでない場合は、ユーザーの PrimaryGroupID をそのグループの RID に設定することはできません。

ADSI で Windows NT プロバイダを使用すると、プライマリ グループがユーザーの IADsUser::Groups コレクションのエントリとして格納されます。

LDAP プロバイダでは、プライマリ グループが IADsUser::Groups コレクションのエントリとして格納されることはありません。また、ディレクトリ内のユーザー オブジェクトの MemberOf 属性を取得し、グループの識別名 (DN) の部分を調べても、プライマリ グループは含まれていません。LDAP ユーザー オブジェクトでユーザーのプライマリ グループが参照されている部分は、PrimaryGroupID のグループ RID だけです。

どちらのプロバイダにも、各ユーザー オブジェクトからプライマリ グループ名を直接取得できるような仕組みは定義されていません。しかも、次に示すとおり、各グループ オブジェクトでサポートされる属性のセットはオブジェクトの提供元のプロバイダによって異なるため、問題はいっそう複雑になります。
  • Windows NT が提供するグループ オブジェクトでは、PrimaryGroupToken 属性がサポートされていません。また、Windows NT プロバイダでは、ネイティブの ADSI コードを使用してグループの RID を取得する方法も一切サポートされていません。
  • LDAP プロバイダのグループ オブジェクトの PrimaryGroupToken 属性は、計算された属性です。この属性は、ディレクトリ内のグループ オブジェクト上に存在するわけではありません。この属性が実際に作成されるのは、IADs::GetInfoEx メソッドの呼び出しによってクライアントから要求されたときです。Active Directory で構築された属性を基に、LDAP 検索を実行することはできません。つまり、LDAP プロバイダでは、プライマリ グループを取得しようとしているユーザー オブジェクトの PrimaryGroupID 属性と PrimaryGroupToken 属性が一致するという条件で、グループを検索することはできません。このため、プライマリ グループを取得する外部の COM オブジェクトに依存しない、純粋な ADSI ソリューションの実現も難しくなります。

ユーザーのプライマリ グループを取得する方法

ユーザーのプライマリ グループの名前を取得する方法としては、次の 3 つが知られています。
  • ユーザーの SID のドメイン RID コンポーネントと、ユーザー オブジェクトの PrimaryGroupID 属性に格納されているグループの RID から、Active Directory 内のグループ オブジェクトに対する SID バインド文字列を構築する。

    これは、「サポート技術情報」の文書番号 Q297951 (この資料の「関連情報」を参照) で説明されている方法です。この方法の大きな問題は、SID バインド文字列を構築するために、ドメイン オブジェクトのバイナリのセキュリティ記述子を SDDL 形式に変換する必要があるという点です。これは、ADsSID オブジェクトに依存することになります。ADsSID オブジェクトは、ADsSecurity.dll ファイルによってホストされます。コードを正しく動作させるためには、事前にこのファイルをクライアントにコピーし、登録しておく必要があります。
  • ドメイン内のすべてのグループ検索してそれぞれの PrimaryGroupToken 属性を返す LDAP クエリを使用する。

    これは純粋な LDAP のソリューションです。ただし、この検索では、ユーザーが所属していないグループも含めてドメイン内のすべてのグループが返されるため、あまり効率のよいソリューションとは言えません。さらに、レコード セットを走査するたびにクライアントで PrimaryGroupToken 属性が構築されるため、検索速度もかなり遅くなります。ドメイン内のグループの数が多い場合は、特に時間がかかる可能性があります。LDAP 構文の ADO クエリを作成する方法の例は、さまざまな場所で紹介されているため、この資料では扱いません。
  • 各プロバイダの機能を利用してハイブリッドなソリューションを構築する。

    このソリューションでは、ユーザーのプライマリ グループを取得するために、複数のプロバイダの機能を利用します。これを行うには、次の手順に従います。
    1. Windows NT プロバイダにユーザー オブジェクトをバインドします。

      Windows NT のユーザー オブジェクトから提供されるグループのコレクションには、ユーザーのプライマリ グループが必ず含まれています。また、このアルゴリズムの後の処理で使用できるように、ユーザー オブジェクトの PrimaryGroupID を一時的に保存します。
    2. IADsUser::Groups コレクションを列挙します。
    3. このコレクションに含まれている各グループの ADsPath から SamAccountName プロパティを抽出し、それを使用して LDAP 構文のクエリ文字列を作成します。このクエリは、コレクションから取得した SamAccountName プロパティと一致する名前のグループをすべて検索し、PrimaryGroupToken 属性および DistinguishedName 属性の値を返すように設計します。
    4. ADO ADSI 検索を実行します。結果のレコード セットをループし、各グループの PrimaryGroupToken を、あらかじめキャッシュしておいた PrimaryGroupID 属性の値と比較します。
    5. 一致が見つかったらループを終了し、そのグループの識別名をユーザーのプライマリ グループとして表示します。
    6. 一致が見つからない場合は、引き続き検索結果をループします。
    この方法の利点はすぐにわかります。使用するオブジェクトはすべて 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 Knowledge Base) をクリックしてください。
297951 HOWTO: Use the PrimaryGroupID Attribute to Find the Primary Group for a User
SID コンポーネントの詳細については、次の MSDN Web サイトを参照してください。
http://msdn.microsoft.com/library/en-us/security/Security/sid_components.asp

関連情報

この資料は米国 Microsoft Corporation から提供されている Knowledge Base の Article ID 321360 (最終更新日 2002-10-11) をもとに作成したものです。

この資料に含まれているサンプル コード/プログラムは英語版を前提に書かれたものをありのままに記述しており、日本語環境での動作は確認されておりません。

プロパティ

文書番号: 321360 - 最終更新日: 2004年5月17日 - リビジョン: 4.0
この資料は以下の製品について記述したものです。
  • Microsoft Windows 2000 Server
  • Microsoft Active Directory Service Interfaces 2.5
  • Microsoft Active Directory Client Extension
キーワード:?
kbinfo KB321360
"Microsoft Knowledge Baseに含まれている情報は、いかなる保証もない現状ベースで提供されるものです。Microsoft Corporation及びその関連会社は、市場性および特定の目的への適合性を含めて、明示的にも黙示的にも、一切の保証をいたしません。さらに、Microsoft Corporation及びその関連会社は、本文書に含まれている情報の使用及び使用結果につき、正確性、真実性等、いかなる表明・保証も行ないません。Microsoft Corporation、その関連会社及びこれらの権限ある代理人による口頭または書面による一切の情報提供またはアドバイスは、保証を意味するものではなく、かつ上記免責条項の範囲を狭めるものではありません。Microsoft Corporation、その関連会社 及びこれらの者の供給者は、直接的、間接的、偶発的、結果的損害、逸失利益、懲罰的損害、または特別損害を含む全ての損害に対して、状況のいかんを問わず一切責任を負いません。(Microsoft Corporation、その関連会社 またはこれらの者の供給者がかかる損害の発生可能性を了知している場合を含みます。) 結果的損害または偶発的損害に対する責任の免除または制限を認めていない地域においては、上記制限が適用されない場合があります。なお、本文書においては、文書の体裁上の都合により製品名の表記において商標登録表示、その他の商標表示を省略している場合がありますので、予めご了解ください。"

フィードバック

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com