2

BackgroundWorker偽装でクラスを使用しようとすると、少し問題があります。Google からの回答に従って、このコードを偽装しました

public class MyImpersonation {

    WindowsImpersonationContext impersonationContext;

    [DllImport("advapi32.dll")]
    public static extern int LogonUserA(String lpszUserName,
        String lpszDomain,
        String lpszPassword,
        int dwLogonType,
        int dwLogonProvider,
        ref IntPtr phToken);
    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern int DuplicateToken(IntPtr hToken,
        int impersonationLevel,
        ref IntPtr hNewToken);

    [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool RevertToSelf();

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public static extern bool CloseHandle(IntPtr handle);

    public bool impersonateValidUser(String userName, String domain, String password) {
        WindowsIdentity tempWindowsIdentity;
        IntPtr token = IntPtr.Zero;
        IntPtr tokenDuplicate = IntPtr.Zero;

        if (RevertToSelf()) {
            if (LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE,
                LOGON32_PROVIDER_DEFAULT, ref token) != 0) {
                if (DuplicateToken(token, 2, ref tokenDuplicate) != 0) {
                    tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                    impersonationContext = tempWindowsIdentity.Impersonate();
                    if (impersonationContext != null) {
                        CloseHandle(token);
                        CloseHandle(tokenDuplicate);
                        return true;
                    }
                }
            }
        }
        if (token != IntPtr.Zero)
            CloseHandle(token);
        if (tokenDuplicate != IntPtr.Zero)
            CloseHandle(tokenDuplicate);
        return false;
    }
}

BackgroundWorkerクラスで使用するまでは、非常にうまく機能していました。この場合、非同期で実行されるコードに偽装を追加しました。エラーはありませんが、非同期メソッドで使用すると偽装が機能しないという問題があります。

コードでは、これは次のようになります。

  • BGWorker をインスタンス化し、イベント ハンドラーを DoWork イベントに追加します。

    _bgWorker = new BackgroundWorker();
    _bgWorker.DoWork += new DoWorkEventHandler(_bgWorker_DoWork);
    
  • 上記のハンドラーでは、何らかのコードを実行する前に偽装が行われます。

    private void _bgWorker_DoWork(object sender, DoWorkEventArgs e) {        
            MyImpersonation myImpersonation = new MyImpersonation();
            myImpersonation.impersonateValidUser(user, domain, pass)        
           //run some code...        
           myImpersonation.undoImpersonation();        
    }
    
  • コードはで起動されます

    BGWorker.RunWorkerAsync();
    

前に述べたように、エラーはスローされません。コードは、偽装を実行していないかのように動作するだけです。つまり、デフォルトの資格情報が使用されます。

さらに、偽装メソッドは true を返すため、偽装は特定のレベルで発生しましたが、おそらく現在のスレッドでは発生していません。

これは、非同期コードが別のスレッドで実行されるために発生する必要があるため、MyImpersonationクラスに何かを追加する必要があります。しかし、何?:)

4

1 に答える 1

0

私はこれと同じ問題を抱えています。DoWork イベントで静的クラスを偽装するバックグラウンド ワーカーがあります。メイン ユーザーがアクセスできないディレクトリを読み取るために、別の Active Domain ユーザーになりすまそうとしています。IDE でアプリケーションを実行している場合、偽装されたユーザーは問題なくファイルを読み取ることができます。ファイル システムからアプリケーションを実行すると、偽装は引き続き発生しますが、偽装されたユーザーにはアクセス権がないことを示す例外がスローされます。

私が読んだことから、それは Assembly:SecurityPermissionAttribute と Assembly:PermissionSetAttribute の設定によるものです。

クラス宣言の前に、次のものがあります。

    <Assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, UnmanagedCode:=True), _
Assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Name:="FullTrust")> 

StartImpersonating() 関数の前に、次のものがあります。

<PermissionSetAttribute(SecurityAction.Demand, Name:="FullTrust")> _

ただし、C# ではなく VB.NET を使用しています。

-D

于 2009-06-22T13:46:11.380 に答える