2010-11-18 6 views
3

Ich möchte einen Remote-Benutzer dynamisch imitieren, um einen Teil des Codes auszuführen. Ich habe viel im Internet gesucht und einige Codes erhalten, um mich zu imitieren. Der Code zum Imitieren wird unterDynamisch angenommene Identität eines Remote-Benutzers - C# und asp.net

gezeigt
namespace Tools 
{ 
#region Using directives. 
// ---------------------------------------------------------------------- 

using System; 
using System.Security.Principal; 
using System.Runtime.InteropServices; 
using System.ComponentModel; 

// ---------------------------------------------------------------------- 
#endregion 

///////////////////////////////////////////////////////////////////////// 

/// <summary> 
/// Impersonation of a user. Allows to execute code under another 
/// user context. 
/// Please note that the account that instantiates the Impersonator class 
/// needs to have the 'Act as part of operating system' privilege set. 
/// </summary> 
/// <remarks> 
/// This class is based on the information in the Microsoft knowledge base 
/// article http://support.microsoft.com/default.aspx?scid=kb;en-us;Q306158 
/// 
/// Encapsulate an instance into a using-directive like e.g.: 
/// 
///  ... 
///  using (new Impersonator("myUsername", "myDomainname", "myPassword")) 
///  { 
///   ... 
///   [code that executes under the new context] 
///   ... 
///  } 
///  ... 
/// 
/// Please contact the author Uwe Keim (mailto:[email protected]) 
/// for questions regarding this class. 
/// </remarks> 
public class Impersonator : 
    IDisposable 
{ 
    #region Public methods. 
    // ------------------------------------------------------------------ 

    /// <summary> 
    /// Constructor. Starts the impersonation with the given credentials. 
    /// Please note that the account that instantiates the Impersonator class 
    /// needs to have the 'Act as part of operating system' privilege set. 
    /// </summary> 
    /// <param name="userName">The name of the user to act as.</param> 
    /// <param name="domainName">The domain name of the user to act as.</param> 
    /// <param name="password">The password of the user to act as.</param> 
    public Impersonator(
     string userName, 
     string domainName, 
     string password) 
    { 
     ImpersonateValidUser(userName, domainName, password); 
    } 

    // ------------------------------------------------------------------ 
    #endregion 

    #region IDisposable member. 
    // ------------------------------------------------------------------ 

    public void Dispose() 
    { 
     UndoImpersonation(); 
    } 

    // ------------------------------------------------------------------ 
    #endregion 

    #region P/Invoke. 
    // ------------------------------------------------------------------ 

    [DllImport("advapi32.dll", SetLastError=true)] 
    private static extern int LogonUser(
     string lpszUserName, 
     string lpszDomain, 
     string lpszPassword, 
     int dwLogonType, 
     int dwLogonProvider, 
     ref IntPtr phToken); 

    [DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)] 
    private static extern int DuplicateToken(
     IntPtr hToken, 
     int impersonationLevel, 
     ref IntPtr hNewToken); 

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

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

    private const int LOGON32_LOGON_INTERACTIVE = 2; 
    private const int LOGON32_PROVIDER_DEFAULT = 0; 

    // ------------------------------------------------------------------ 
    #endregion 

    #region Private member. 
    // ------------------------------------------------------------------ 

    /// <summary> 
    /// Does the actual impersonation. 
    /// </summary> 
    /// <param name="userName">The name of the user to act as.</param> 
    /// <param name="domainName">The domain name of the user to act as.</param> 
    /// <param name="password">The password of the user to act as.</param> 
    private void ImpersonateValidUser(
     string userName, 
     string domain, 
     string password) 
    { 
     WindowsIdentity tempWindowsIdentity = null; 
     IntPtr token = IntPtr.Zero; 
     IntPtr tokenDuplicate = IntPtr.Zero; 

     try 
     { 
      if (RevertToSelf()) 
      { 
       if (LogonUser(
        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(); 
        } 
        else 
        { 
         throw new Win32Exception(Marshal.GetLastWin32Error()); 
        } 
       } 
       else 
       { 
        throw new Win32Exception(Marshal.GetLastWin32Error()); 
       } 
      } 
      else 
      { 
       throw new Win32Exception(Marshal.GetLastWin32Error()); 
      } 
     } 
     finally 
     { 
      if (token!= IntPtr.Zero) 
      { 
       CloseHandle(token); 
      } 
      if (tokenDuplicate!=IntPtr.Zero) 
      { 
       CloseHandle(tokenDuplicate); 
      } 
     } 
    } 

    /// <summary> 
    /// Reverts the impersonation. 
    /// </summary> 
    private void UndoImpersonation() 
    { 
     if (impersonationContext!=null) 
     { 
      impersonationContext.Undo(); 
     } 
    } 

    private WindowsImpersonationContext impersonationContext = null; 

    // ------------------------------------------------------------------ 
    #endregion 
} 

///////////////////////////////////////////////////////////////////////// 
    } 

und der Code, der die oben genannten Funktionen aufruft, wird unter

using System; 
using System.IO; 
using Tools; 

namespace ImpersonatorDemo 
{ 
/// <summary> 
/// Main class for the demo application. 
/// Call this application with a low privileg account to test. 
/// </summary> 
class Program 
{ 
    /// <summary> 
    /// The main entry point. 
    /// </summary> 
    [STAThread] 
    static void Main(string[] args) 
    { 
     // Impersonate, automatically release the impersonation. format is new Impersonator("username", "domain", "password") 
     using (new Impersonator("TestUser", "MachineA", "admin")) 
     { 
      string name = Environment.UserDomainName; 
      string s = Environment.UserName; 
      // The following code is executed under the impersonated user. 
      string[] files = Directory.GetFiles("c:\\"); 
     } 
    } 
} 
} 

Es funktioniert gut angezeigt, wenn ich versuche, Benutzer auf dem lokalen Computer zu imitieren. Aber wenn ich versuche, einen Benutzer auf dem entfernten Rechner imporsenate wirft es immer einen Fehler .which unter

  Logon failure: unknown user name or bad password 

in der entfernten Maschine ein Benutzer mit dem Namen angezeigt wird Testuser ist und das Passwort ist admin und Maschinenname ist MachineA (wird Thi ist Domain-Name ??) und die IP-Adresse ist 192.168.0.33. Die Arbeitsgruppe ist myWorkGroup. Ich habe versucht, Benutzer auf vielen mremote-Rechnern zu imitieren. Aber es zeigt immer den gleichen Fehler, den ich oben geschrieben habe, wenn ich versucht werde, mich als Remote-Benutzer auszugeben. und ich bin sicher, dass meine lokale Computer mit dem Netzwerk verbunden

Antwort

1

Impersonate ist nicht so einfach wie es aussieht. Während der Code zum Imitieren ist ziemlich einfach, möglicherweise nicht finden die Argumente. Es hängt davon ab, wie Sie Ihren Benutzer authentifizieren müssen -> eine Arbeitsgruppe unterscheidet sich von einer Domäne von einer Maschine, etc ...
Für Ihre Arbeitsgruppe ist es wichtig, ob der Benutzer auf beiden Maschinen bekannt ist oder nicht. Als einfachen technischen Ansatz sollten Sie versuchen, den Domänen-/Computernamen leer zu lassen.
auch Ricks Post überprüfen, sind die Double-Hop Sachen ziemlich ärgerlich, wenn sie mit dem Identitätswechsel woring :(

5

Wie ich Ihr Problem zu verstehen, über der ImpersonateDemo Code läuft auf dem Server (ServerA).

ServerA versucht, ein bekommen Liste der Dateien auf einem entfernten Rechner (MachineA)

Wenn Ihr Code auf ServerA die Dateien in der C-Anfragen:.. \ Verzeichnis, das Sie immer die Dateien auf dem Server des C-Laufwerk bekommen geht

aus diesem Grunde Wenn Sie einen lokalen Benutzer (auf ServerA) annehmen, funktioniert es - weil der Benutzer auf dem Computer ist dass das Laufwerk eingeschaltet ist. Wenn Sie mit dem Remotebenutzer (von MachineA) imitieren, versuchen Sie immer noch, den Inhalt des C-Laufwerks von ServerA zu erhalten, aber dieser Benutzer existiert nicht auf ServerA.

Sie müssen Dateien basierend auf der IP-Adresse (oder dem Computernamen) des Remote-Rechners anfordern. Wenn der Testbenutzer berechtigt ist, das Laufwerk C von MachineA zu lesen, versuchen Sie Folgendes:

string[] files = Directory.GetFiles(@"\\192.168.0.33\C$"); 
string[] files = Directory.GetFiles(@"\\MachineA\C$"); 
Verwandte Themen