Impersonation using ASP.NET Membership Provider

2020-02-15 05:38发布

问题:

I have a custom membership/roles provider, due to the nature of the project it will require admins to login as users while assisting them with queries.

Now, Its easy to re-log the admin in with the selected membership account, however this means that the admin will effectively be logged out. I'm looking for a way to allow admins to impersonate users yet very easily switch back to there own account at any time.

Any suggestions?

回答1:

This should be the sort of thing you want.

You can call the ImpersonateValidUser method with the username and password of the domain account you want. And then reverse it on the logout.

You should be able to bend this to work with your custom membership provider.

// Constants for impersonation
private WindowsImpersonationContext impersonationContext;
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;

/// <summary>
/// Changes the account we are running under. 
/// </summary>
/// <param name="username">Username of a local admin account</param>
/// <param name="domain">Domain of the username</param>
/// <param name="password">Password of a local admin account</param>
/// <returns></returns>
private bool ImpersonateValidUser(String username, String domain, String password)
{
    WindowsIdentity tempWindowsIdentity;
    IntPtr token = IntPtr.Zero;
    IntPtr tokenDuplicate = IntPtr.Zero;

    if (RevertToSelf())
    {
        if (LogonUserA(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();
                if (impersonationContext != null)
                {
                    CloseHandle(token);
                    CloseHandle(tokenDuplicate);
                    return true;
                }
            }
        }
    }
    if (token != IntPtr.Zero)
        CloseHandle(token);
    if (tokenDuplicate != IntPtr.Zero)
        CloseHandle(tokenDuplicate);
    return false;
}

/// <summary>
/// Cancel the impersonation and revent the thread to the
/// default account. Typically DOMAIN\NETWORK_SERVICE or similar.
/// </summary>
private void UndoImpersonation()
{
    impersonationContext.Undo();
}