【问题标题】:Dynamically Impersonate a remote user - c# and asp.net动态模拟远程用户 - c# 和 asp.net
【发布时间】:2011-05-11 22:36:41
【问题描述】:

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

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:uwe.keim@zeta-software.de)
/// 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
}

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

调用上述函数的代码如下所示

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:\\" );
        }
    }
}
 }

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

            Logon failure: unknown user name or bad password

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

【问题讨论】:

    标签: c# asp.net impersonation


    【解决方案1】:

    【讨论】:

      【解决方案2】:

      模拟并不像看起来那么简单。虽然模拟代码非常简单,但查找参数可能并非如此。这取决于您需要对用户进行身份验证的方式 -> 工作组不同于域 不同于机器等...
      对于您的工作组而言,用户是否在两台机器上都知道这一点很重要。作为一种简单的技术方法,您应该尝试将域/机器名称留空。
      另请查看 Ricks 的帖子,在使用模拟时,双跳的东西非常烦人:(

      【讨论】:

        【解决方案3】:

        据我了解您的问题,上面的 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$" );
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-02-19
          • 2017-12-10
          • 2012-01-24
          • 1970-01-01
          • 1970-01-01
          • 2014-02-18
          • 2014-02-10
          • 2012-09-28
          相关资源
          最近更新 更多