En http://msdn.microsoft.com/en-us/library/w070t6ka(v=VS.100).aspx hay un ejemplo sobre cómo hacer una suplantación con .net 4.0. Hemos utilizado este ejemplo en una clase que hereda IDisposable para facilitar su uso. Sin embargo, cuando usamos esta clase en una aplicación web asp.net, notamos un aumento leve pero constante de Bytes agrupados en el monitor de rendimiento. Después de una semana, la aplicación falla.Fuga de memoria de suplantación
He intentado diferentes implementaciones de la clase de suplantación, usando http://msdn.microsoft.com/en-us/library/w070t6ka(v=VS.90).aspx y http://support.microsoft.com/kb/306158 como referencia, pero todas muestran la misma fuga.
¿De dónde viene esta fuga? ¿Hay algún problema con la API de Windows? Estamos ejecutando Windows 2008 R2.
Ésta es nuestra versión actual de la clase suplantación:
public class Impersonator : IDisposable
{
public Impersonator(string username, string domain, string password)
{
if (!ImpersonateValidUser(username, domain, password))
{
throw new SecurityException("Could not impersonate. Wrong username/password");
}
}
public void Dispose()
{
UndoImpersonation();
}
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
private static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out SafeTokenHandle phToken);
private const int LOGON32_PROVIDER_DEFAULT = 0;
private const int LOGON32_LOGON_INTERACTIVE = 2; //This parameter causes LogonUser to create a primary token.
private WindowsImpersonationContext impersonatedUser;
private bool ImpersonateValidUser(string username, string domain, string password)
{
SafeTokenHandle safeTokenHandle;
// Call LogonUser to obtain a handle to an access token.
bool success = LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out safeTokenHandle);
if (success)
{
using (safeTokenHandle)
{
// Use the token handle returned by LogonUser.
WindowsIdentity newId = new WindowsIdentity(safeTokenHandle.DangerousGetHandle());
impersonatedUser = newId.Impersonate();
}
}
return success;
}
private void UndoImpersonation()
{
// Releasing the context object stops the impersonation
if (impersonatedUser != null)
{
impersonatedUser.Undo();
impersonatedUser.Dispose();
}
}
}
public sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid
{
private SafeTokenHandle() : base(true)
{
}
[DllImport("kernel32.dll")]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool CloseHandle(IntPtr handle);
protected override bool ReleaseHandle()
{
return CloseHandle(handle);
}
}
Y este es el gráfico de monitor de rendimiento de los dos servidores web utilizando diferentes versiones de la clase:
perfmon http://img222.imageshack.us/img222/5388/captureyog.png
Cuando desactivamos la clase, y usar la suplantación global a través de web.config, esas líneas son completamente planas.
actualización
he hecho una prueba de aplicación que reproduce con éxito el problema. Se puede descargar aquí:
http://rapidshare.com/files/447325211/ImpersonationTest.zip
El resultado más de 18 horas se ve así:
testapp http://img689.imageshack.us/img689/2055/impersonationtest.png
He echado un vistazo a su código y a la implementación de SafeHandleZeroOrMinusOneIsInvalid (a través de Reflector). Estoy seguro de que probablemente me haya perdido algo, pero no tengo claro de dónde se llamará a CloseHandle o ReleaseHandle. ¿Está esperando que fue llamado por el método Dispose heredada en SafeTokenHandle? – MikeD
No tengo idea de cómo funciona, solo asumo que sí, ya que está copiado del sitio de Microsoft en el enlace de arriba. He agregado algunas líneas de depuración, y se llama después de que se hace la suplantación, pero eso es todo lo que sé. – TheQ
Dado lo que dices y que las otras muestras cierran explícitamente el identificador, entonces no parece ser el problema. ¿Tienes una suscripción a MSDN? De ser así, podría usar un incidente de soporte técnico de Microsoft para obtener ayuda adicional. – MikeD