动态模拟远程用户 – c#和asp.net

我想动态模拟远程用户执行某些代码。 我在网上搜索了很多,并得到了一些代码来冒充。 模仿的代码如下所示

namespace Tools { #region Using directives. // ---------------------------------------------------------------------- using System; using System.Security.Principal; using System.Runtime.InteropServices; using System.ComponentModel; // ---------------------------------------------------------------------- #endregion ///////////////////////////////////////////////////////////////////////// ///  /// 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. ///  ///  /// 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 eg: /// /// ... /// using ( new Impersonator( "myUsername", "myDomainname", "myPassword" ) ) /// { /// ... /// [code that executes under the new context] /// ... /// } /// ... /// /// Please contact the author Uwe Keim (mailto:uwe.keim@zeta-software.de) /// for questions regarding this class. ///  public class Impersonator : IDisposable { #region Public methods. // ------------------------------------------------------------------ ///  /// 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. ///  /// The name of the user to act as. /// The domain name of the user to act as. /// The password of the user to act as. 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. // ------------------------------------------------------------------ ///  /// Does the actual impersonation. ///  /// The name of the user to act as. /// The domain name of the user to act as. /// The password of the user to act as. 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 ); } } } ///  /// Reverts the impersonation. ///  private void UndoImpersonation() { if ( impersonationContext!=null ) { impersonationContext.Undo(); } } private WindowsImpersonationContext impersonationContext = null; // ------------------------------------------------------------------ #endregion } ///////////////////////////////////////////////////////////////////////// } 

调用上述function的代码如下所示

 using System; using System.IO; using Tools; namespace ImpersonatorDemo { ///  /// Main class for the demo application. /// Call this application with a low privileg account to test. ///  class Program { ///  /// The main entry point. ///  [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:\\" ); } } } } 

如果我尝试在本地计算机上模拟用户,它工作正常 。 但是如果我试图在远程机器上冒充用户,它总会抛出一个错误。如下所示

  Logon failure: unknown user name or bad password 

在远程机器中有一个名为Testuser的用户,密码是admin,机器名是MachineA(这是域名吗?),IP地址是192.168.0.33。 工作组是myWorkGroup。我试图模仿许多mremote机器上的用户。 但它总是显示我上面写的相同的错误,如果我试图冒充远程用户。 我确信我的本地机器已连接到网络

据我了解您的问题,上面的ImpersonateDemo代码在您的服务器(ServerA)上运行。

ServerA尝试获取远程计算机(MachineA)上的文件列表。

如果ServerA上的代码请求C:\目录中的文件,您将始终获取服务器C驱动器上的文件。

这就是为什么当你冒充本地用户(在ServerA上)它可以工作时 – 因为用户在驱动器所在的机器上。 当您模拟远程用户(来自MachineA)时,您仍在尝试获取ServerA的C驱动器的内容,但该用户在ServerA上不存在。

您需要根据远程计算机的IP地址(或计算机名称)请求文件。 如果TestUser有权读取MachineA的C盘,那么试试这个:

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

模仿并不像看起来那么简单。 虽然模拟的代码非常简单,但查找参数可能不是。 这取决于您对用户进行身份validation所需的方式 – >工作组与域的不同与机器等不同…
对于您的工作组,如果用户在两台机器上都知道,那么这很重要。 作为一种简单的技术方法,您应该尝试将域/机器名称留空。
同时检查Rickspost,双跳的东西在冒充模仿时非常讨厌:(