ASP.Net WindowsImpersonate.Impersonator.Undo не работает - PullRequest
0 голосов
/ 11 января 2019

Небольшой класс C # для олицетворения пользователя

Я внедряю WindowsImpersonate на своем сайте asp.net. Я нашел этот класс онлайн: https://www.codeproject.com/Articles/10090/A-small-C-Class-for-impersonating-a-User?fid=171054&fr=151#xx0xx, который действительно хорошо работает:

using (var imp = new Tools.Impersonator("username", "domain", "password"))
{

}

на моем локальном хосте я вижу (при отладке), что пользователь переходит от MyLoggedInUser к ImpersonatedUser и затем обратно к MyLoggedInUser после использования оператора end .

Однако, когда я загружаю все в IIS, он переходит от MyLoggedInUser к ImpersonatedUser , а затем остается ImpersonatedUser даже после оператора using.

Я пытался напрямую вызвать метод Dispose для подражательного объекта, но (как и ожидалось) получил те же результаты.

Метод Undo вызывается в Dispose (), и, как я уже сказал, он отлично работает в localhost, но на моем сервере IIS нет.

Есть идеи?

Это фактический класс имитатора:

Инструменты пространства имен {

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

/// <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();
            impersonationContext.Dispose();
        }
    }

    private WindowsImpersonationContext impersonationContext = null;

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

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

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...