2009-06-15 10 views
4

私はのLogonUser Win32 APIのを使用しています: のLogonUserと委任

token = LogonUser(...) 
WindowsIdentity newId = new WindowsIdentity(token);    
WindowsImpersonationContext impersonatedUser = newId.Impersonate(); 

は、しかし、この後にWCFサービスを呼び出す私は、偽装IDを使用することはできませんよ。これは、impersonatedUser.ImpersonationLevelが偽装と等しいためです。

これが理由ですか? 私は必要なレベルのImpersonationLevel.Identificationですか? このようなレベルを取得するには?

答えて

8

これがWCFで動作するかどうかわかりません。しかし、我々はファイルシステムにファイルを読み書きする偽装のために、プロダクションウェブアプリケーションでそれを使用します。 AdvApi32.LogonUser、AdvApi32.DuplicateToken、およびKernel32.CloseHandleのAPIを定義し、完了したらWindowsImpersonationContextを閉じる必要があります。この後

/// <summary>impersonates a user</summary> 
    /// <param name="username">domain\name of the user account</param> 
    /// <param name="password">the user's password</param> 
    /// <returns>the new WindowsImpersonationContext</returns> 
    public static WindowsImpersonationContext ImpersonateUser(String username, String password) 
    { 
     WindowsIdentity winId = WindowsIdentity.GetCurrent(); 
     if (winId != null) 
     { 
      if (string.Compare(winId.Name, username, true) == 0) 
      { 
       return null; 
      } 
     } 

     //define the handles 
     IntPtr existingTokenHandle = IntPtr.Zero; 
     IntPtr duplicateTokenHandle = IntPtr.Zero; 

     String domain; 
     if (username.IndexOf("\\") > 0) 
     { 
      //split domain and name 
      String[] splitUserName = username.Split('\\'); 
      domain = splitUserName[0]; 
      username = splitUserName[1]; 
     } 
     else 
     { 
      domain = String.Empty; 
     } 

     try 
     { 
      //get a security token 

      bool isOkay = AdvApi32.LogonUser(username, domain, password, 
       (int) AdvApi32.LogonTypes.LOGON32_LOGON_INTERACTIVE, 
       (int) AdvApi32.LogonTypes.LOGON32_PROVIDER_DEFAULT, 
       ref existingTokenHandle); 

      if (!isOkay) 
      { 
       int lastWin32Error = Marshal.GetLastWin32Error(); 
       int lastError = Kernel32.GetLastError(); 

       throw new Exception("LogonUser Failed: " + lastWin32Error + " - " + lastError); 
      } 

      // copy the token 

      isOkay = AdvApi32.DuplicateToken(existingTokenHandle, 
       (int) AdvApi32.SecurityImpersonationLevel.SecurityImpersonation, 
       ref duplicateTokenHandle); 

      if (!isOkay) 
      { 
       int lastWin32Error = Marshal.GetLastWin32Error(); 
       int lastError = Kernel32.GetLastError(); 
       Kernel32.CloseHandle(existingTokenHandle); 
       throw new Exception("DuplicateToken Failed: " + lastWin32Error + " - " + lastError); 
      } 
      // create an identity from the token 

      WindowsIdentity newId = new WindowsIdentity(duplicateTokenHandle); 
      WindowsImpersonationContext impersonatedUser = newId.Impersonate(); 

      return impersonatedUser; 
     } 
     finally 
     { 
      //free all handles 
      if (existingTokenHandle != IntPtr.Zero) 
      { 
       Kernel32.CloseHandle(existingTokenHandle); 
      } 
      if (duplicateTokenHandle != IntPtr.Zero) 
      { 
       Kernel32.CloseHandle(duplicateTokenHandle); 
      } 
     } 
    } 
+0

WindowsIdentityのインスタンスを作成することに興味がある人には、 'WindowsIdentity.Dispose()'はそのトークンハンドルを閉じます。つまり、 'Dispose'を呼び出すときに' CloseHandle(duplicateTokenHandle) 'を呼び出す必要はありません。 – Joh

+0

@Joh - それは正しいとは思わない。 'Dispose' *は' CloseHandle() 'を呼び出しますが、コンストラクタに渡されたハンドルは呼び出しません。コンストラクタは、指定されたハンドルを複製します。それは 'Dispose'で閉じられた複製です。 – Olly

1

私は を使用することはできませんよ偽装が同じボックスではなく、ネットワーク上のアクセスのために効果的であるべき

身元を偽装。

ログオントークンを使用する前に偽装トークンに変換するためには、consultutahのコードに示すように、DuplicateToken()を呼び出すだけで済みます。

これは、impersonatedUser.ImpersonationLevelが偽装と等しいためです。

他のシステムの偽装ユーザーとして行動する必要がある場合は、「委任」と呼ばれる偽装のレベルを上げる必要があります。これは、基本的にはユーザーのパスワードを持つことと同じで、自分自身を他者に表すことができます。