Questa classe incapsula una serie di dichiarazioni P/INVOKE per la modifica a runtime dell'utente loggato al sistema, utile ad esempio se da una pagina ASP.NET occorre accedere MOMENTANEAMENTE a risorse accessibili solo come utente != ASP.NET...

Chiaramente occhio a quello che fate...

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

namespace GisSharpBlog.Logging
{
    
/// <summary>
    /// 
Changes the account logged to system.
    
/// </summary>
    
public class ImpersonationChanger : IDisposable
    {        
        
#region STATIC P/INVOKE DECLARATIONS

        
[DllImport("advapi32.dll")]
        
private static extern int LogonUser(string userName, string domain, string password,
                                            
int logonType, int logonProvider, ref IntPtr token);

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

        [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);        

        
#endregion

        #region PARAMETERS
        
        private const int 
LOGON32_LOGON_NETWORK = 3;
        
private const int LOGON32_PROVIDER_DEFAULT = 0;    

        
#endregion
        
        #region CLASS IMPL

        private 
WindowsImpersonationContext impersonationContext = null;

        
private string domain = String.Empty;
        
private string username = String.Empty;        
        
private string password = String.Empty;
                
        
public ImpersonationChanger(string domain, string username, string password)
        {
            
this.domain = domain;
            
this.username = username;
            
this.password = password;
        }

        
/// <summary>
        /// 
Log to system with modified user informations.
        
/// </summary>        
        /// <exception cref="ApplicationException">
If wrong user parameters are used.</exception>
        
public WindowsImpersonationContext ImpersonateValidUser()
        {
            WindowsIdentity windowsIdentity = 
null;
            IntPtr token = IntPtr.Zero;            

            
if(RevertToSelf())
            {
                
if(LogonUser(username, domain, password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, ref token) != 0)
                {                    
                    windowsIdentity = 
new WindowsIdentity(token);    
                    impersonationContext = windowsIdentity.Impersonate();
                    
if (impersonationContext != null)
                    {                        
                        CloseHandle(token);                        
                        
return impersonationContext;
                    }
                }
            }
            
if(token != IntPtr.Zero)    
                CloseHandle(token);            
            
throw new ApplicationException("Should never reach here!");
        }

        
/// <summary>
        /// 
Revert changes.
        
/// </summary>
        /// <param name="impersonationContext"></param>
        
public void UndoImpersonation()
        {        
            
if(impersonationContext != null)
                impersonationContext.Undo();
            impersonationContext = 
null;
        }

        
#endregion

        #region IDISPOSABLE IMPL

        
/// <summary>
        /// 
        /// </summary>
        
public virtual void Dispose()
        {
            Dispose(
true);
            GC.SuppressFinalize(
this);            
        }

        
protected virtual void Dispose(bool disposing) 
        {
            
if (disposing)             
                UndoImpersonation();    
            impersonationContext = 
null;
        }
        
        ~ImpersonationChanger()
        {
            Dispose (
false);
        }

        
#endregion
    
}
}

download code

Ecco come si usa:

using(new GisSharpBlog.Logging.ImpersonationChanger("domain", "username", "password"))
{
    
// Do work with new log user credentials...
}
// Continue with old credentials...

Difficile, no? Sia benedetto il pattern Dispose...

Posto un paio di configurazioni: questo codice mi serviva per accedere a dei files in rete locale da un WebService, cosa che l'utente normale ASP.NET non permette di fare; ora, non sono riuscito a compiere tale operazione utilizzando questa classe (da alcuni post trovati su internet pare che non sia possibile se non modificando il file machine.config, cosa che è una autentica pazzia come pure Lorenzo non ha mancato di farmi notare...), ma apparentemente la fase di log funziona correttamente... nel caso abbiate voglia di fare dei test segnalatemi pure eventuali problemi.

Buon lavoro

powered by IMHO 1.3