2009-06-15 2 views
4

Я использую Win32 API LogonUser:LogonUser и делегация

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

Однако при вызове службы WCF после этого я не могу использовать олицетворение идентичности. Я думаю, это связано с тем, что impersonatedUser.ImpersonationLevel равен олицетворению.

Это причина? Является ли уровень ImpersonationLevel.Identification тем, что мне нужно? Как получить такой уровень?

ответ

8

Я не знаю, будет ли это работать для WCF. Но мы используем его в нашем производственном веб-приложении для олицетворения для чтения и записи файлов в файловую систему. Вам нужно будет определить API для AdvApi32.LogonUser, AdvApi32.DuplicateToken и Kernel32.CloseHandle и не забудьте закрыть 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()' закрывает дескриптор маркера, то есть вам не нужен вызов 'CloseHandle (duplicateTokenHandle)', если вы вызываете 'Dispose'. – Joh

+0

@Joh - Я не думаю, что это правильно. 'Dispose' * does * вызывает' CloseHandle() ', но не на дескриптор, переданный в конструктор. Конструктор дублирует поставляемую ручку; это дубликат, который закрыт в 'Dispose'. – Olly

1

после этого я не в состоянии использовать олицетворенного тождество

олицетворение должно быть эффективным для доступа на том же поле, но не в сети.

Может быть, как показывает код consultutah, вам просто нужно вызвать DuplicateToken(), чтобы преобразовать токен входа в токен олицетворения, прежде чем его можно будет использовать.

Я думаю, что это потому, что имперсоналИсполнение.ИмперсонажЛейвер равен олицетворению.

Если вам нужно действовать как олицетворяемый пользователь в других системах, вам нужен более высокий уровень олицетворения, называемый «делегирование». Это в основном эквивалентно тому, что у пользователя есть пароль, чтобы вы могли представлять себя как их для других.

 Смежные вопросы

  • Нет связанных вопросов^_^