5

現在のプロジェクトでは、Active Directory グループに対してユーザーを検証する必要があります。問題は、コンピューターが常にドメインに接続されているとは限らず、ユーザーがツールを実行する必要がある場合があることです。接続していない間は Active Directory にクエリを実行できないことを理解しています。代わりに、Machine SAM (MSAM) にクエリを実行しようとしています。

ネットワークから切断されている間、現在のユーザーを特定できません。これが私が使用しているものです:

PrincipalContext principalctx = new PrincipalContext(ContextType.Machine);
UserPrincipal uprincipal = new UserPrincipal(principalctx);

この時点から、現在ローカル マシンにログインしているユーザーを確認するにはどうすればよいでしょうか。

ドメインに接続すると、 を使用してクエリを実行できますUserPrincipal.Current。ドメインに接続していない場合、 と言って失敗します"The server could not be contacted"。注: このメソッドは、上記のコードを使用して使用することはできません。代わりにPrincipalContext、現在のユーザーを直接クエリすることはできません。現在のユーザーが特定されGetGroups()たら、必要なグループのいずれかに属しているかどうかを照会して判断できます。

また、誰かが 3 つContextTypeのオプションについて説明してくださいApplicationDirectory, Domain, Machine。各オプションを完全に理解していないため、間違って使用している可能性があります。

4

2 に答える 2

10

上から:

現在のプロジェクトでは、Active Directory グループに対してユーザーを検証する必要があります。問題は、コンピューターが常にドメインに接続されているとは限らず、ユーザーがツールを実行する必要がある場合があることです。

したがって、この時点で、強制されたセキュリティはすべてクライアントで強制されるため、攻撃者によってバイパスされる可能性があることを受け入れる必要があります。解決策の一部ではありませんが、覚えておいてください。

接続していない間は Active Directory にクエリを実行できないことを理解しています。代わりに、Machine SAM (MSAM) にクエリを実行しようとしています。

セキュリティ アカウント マネージャーは、ローカル アカウント (MACHINENAME\Administrator など) のみを格納します。ドメイン ユーザー資格情報はありません。最後の N ドメイン ログインの資格情報 (N は、グループ ポリシーによって構成された 0 から 50 の数字) と最後の N SID から名前のマッピング (既定値は 128、レジストリで構成可能) を記憶するLSA キャッシュについて考えています。セキュリティ アカウント マネージャーは、ドメイン アカウントをドメイン コントローラーにのみ格納します。

ネットワークから切断されている間、現在のユーザーを特定できません。これが私が使用しているものです: PrincipalContext principalctx = new PrincipalContext(ContextType.Machine); UserPrincipal uprincipal = 新しい UserPrincipal(principalctx);

また、ContextType の ApplicationDirectory、Domain、Machine の 3 つのオプションについて説明してください。各オプションを完全に理解していないため、間違って使用している可能性があります。

上記のように、情報はキャッシュされませんが、ContextType 列挙型は次のように記述できます。

MSDN から:

  • ドメイン:ドメイン ストア。これは、AD DS ストアを表します。(それが言うように、これは Active Directory の LDAP ディレクトリ アクセスのように、ドメイン アカウント用です - これにはネットワーク アクセスが必要です)
  • ApplicationDirectory:アプリケーション ディレクトリ ストア。これは AD LDS ストアを表します。( AD Lightweight Directory Services (以前は ADAM と呼ばれていました) は、単一のアプリケーションの資格情報を格納するように設計された Active Directory の小型バージョンです。この説明には関係ありませんが、LDAP も使用します。)
  • マシン:コンピューター ストア。これは SAM ストアを表します。(ローカル アカウントのみを列挙します)

この時点から、現在ローカル マシンにログインしているユーザーを確認するにはどうすればよいでしょうか。

を呼び出して、ログオンしているユーザーをいつでも調べることができますWindowsIdentity.GetCurrent()。これは、ログインがオフライン中に発生した場合、ログインしているユーザーの SID とグループ SID を返します。キャッシュされている可能性があります。

ドメインに接続すると、UserPrincipal.Current を使用してクエリを実行できます。ドメインに接続していない場合、「サーバーに接続できませんでした」と表示されて失敗します。注: このメソッドは、上記のコードを使用して使用することはできません。代わりに、PrincipalContext を無視して、現在のユーザーを直接クエリすることができます。現在のユーザーを特定したら、GetGroups() をクエリして、必要なグループのいずれかに属しているかどうかを判断できます。

グループ メンバーシップを確認するには、目的のグループの SID が によって返される ID に含まれているかどうかを確認しWindowsIdentity.GetCurrentます。アクセス制御システムで SID を使用していない場合は、SecurityIdentifier.Translateを呼び出して名前を SID に変換できます。オンラインで翻訳し、オフラインで使用するためにキャッシュする必要があります。文字列またはバイナリとして保存できるため、どちらもレジストリにうまく収まります。

// while we are online, translate the Group to SID
// Obviously, administrators would be a bad example as it is a well known SID...
var admins = new NTAccount("Administrators");
var adminSid = (SecurityIdentifier)admins.Translate(typeof(SecurityIdentifier));

// store the sid as a byte array on disk somewhere 
byte[] adminSIDbytes = new byte[adminSid.BinaryLength];
adminSid.GetBinaryForm(adminSIDbytes, 0);

// at time of check, retrieve the sid and check membership
var sidToCheck = new SecurityIdentifier(adminSIDbytes, 0);
if (!wi.Groups.Contains(sidToCheck))
    throw new UnauthorizedAccessException("User is not a member of required group");
于 2013-07-16T23:59:57.087 に答える