Cómo implementar la suplantación en una aplicación ASP.NET

Seleccione idioma Seleccione idioma
Id. de artículo: 306158 - Ver los productos a los que se aplica este artículo
Este artículo hace referencia a los siguientes espacios de nombres de la Biblioteca de clases de Microsoft .NET Framework:
  • System.Web.Security
  • System.Security.Principal
  • System.Runtime.InteropServices
Expandir todo | Contraer todo

En esta página

Resumen

Este artículo describe diferentes maneras de implementar la suplantación en una aplicación ASP.NET.

Más información

Si desea suplantar a un usuario en un subproceso de ASP.NET, puede utilizar alguno de los métodos siguientes en función de sus necesidades: Nota: puede utilizar el código siguiente para determinar con qué usuario se está ejecutando el subproceso:
System.Security.Principal.WindowsIdentity.GetCurrent().Name
				

Suplantar la cuenta o el usuario autenticados de IIS

Para suplantar al usuario que se está autenticando en Microsoft Internet Information Services (IIS) en todas las solicitudes de todas las páginas de la aplicación ASP.NET, debe incluir la etiqueta <identity> en el archivo Web.config de esta aplicación y configurar el atributo impersonate en true. Por ejemplo:
<identity impersonate="true" />
				

Suplantar a un usuario específico para todas las solicitudes de una aplicación ASP.NET

Para suplantar a un usuario específico para todas las solicitudes de todas las páginas de una aplicación ASP.NET, puede especificar los atributos userName y password en la etiqueta <identity> del archivo Web.config de esa aplicación. Por ejemplo:
<identity impersonate="true" userName="accountname" password="password" />
				
Nota: la identidad del proceso que suplanta a un usuario específico en el subproceso debe tener el privilegio "Actuar como parte del sistema operativo". De manera predeterminada, el proceso Aspnet_wp.exe se ejecuta bajo una cuenta de equipo llamada ASPNET. Sin embargo, esta cuenta no tiene los privilegios necesarios para suplantar a un usuario específico. Recibirá un mensaje de error si intenta suplantar a un usuario específico. Esta información solo se aplica a la versión .NET Framework 1.0. Este privilegio no se requiere para.NET Framework 1.1.

Como solución alternativa para este problema, utilice uno de los métodos siguientes:
  • Conceda el privilegio "Actuar como parte del sistema operativo" a la cuenta ASPNET (la cuenta con menos privilegios).

    Nota: aunque puede utilizar este método para solucionar el problema, Microsoft no lo recomienda.
  • Cambie la cuenta que ejecuta el proceso Aspnet_wp.exe en la cuenta Sistema en la sección de configuración <processModel> del archivo Machine.config

Suplantar al usuario que se autentica en el código

Para suplantar al usuario que se autentica (User.Identity) solo cuando se ejecuta una sección concreta de código, puede utilizar el código siguiente. Este método requiere que la identidad del usuario que se autentica sea del tipo WindowsIdentity.

Visual Basic .NET
Dim impersonationContext As System.Security.Principal.WindowsImpersonationContext
Dim currentWindowsIdentity As System.Security.Principal.WindowsIdentity

currentWindowsIdentity = CType(User.Identity, System.Security.Principal.WindowsIdentity)
impersonationContext = currentWindowsIdentity.Impersonate()

'Inserte aquí el código que se ejecuta en el contexto de seguridad del usuario que se autentica.

impersonationContext.Undo()
				
Visual C# .NET
System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext = 
    ((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();

//Inserte aquí el código que se ejecuta en el contexto de seguridad del usuario que se autentica.

impersonationContext.Undo();
				
Visual J# .NET
System.Security.Principal.WindowsImpersonationContext impersonationContext;
impersonationContext = 
    ((System.Security.Principal.WindowsIdentity)get_User().get_Identity()).Impersonate();

//Inserte aquí el código que se ejecuta en el contexto de seguridad del usuario que se autentica.

impersonationContext.Undo();
				

Suplantar a un usuario específico en el código

Para suplantar a un usuario específico solo cuando se ejecuta una sección concreta de código, utilice el código siguiente.

Visual Basic .NET
<%@ Page Language="VB" %>
<%@ Import Namespace = "System.Web" %>
<%@ Import Namespace = "System.Web.Security" %>
<%@ Import Namespace = "System.Security.Principal" %>
<%@ Import Namespace = "System.Runtime.InteropServices" %>

<script runat=server>
Dim LOGON32_LOGON_INTERACTIVE As Integer = 2
Dim LOGON32_PROVIDER_DEFAULT As Integer = 0

Dim impersonationContext As WindowsImpersonationContext

Declare Function LogonUserA Lib "advapi32.dll" (ByVal lpszUsername As String, _
                        ByVal lpszDomain As String, _
                        ByVal lpszPassword As String, _
                        ByVal dwLogonType As Integer, _
                        ByVal dwLogonProvider As Integer, _
                        ByRef phToken As IntPtr) As Integer

Declare Auto Function DuplicateToken Lib "advapi32.dll" ( _
                        ByVal ExistingTokenHandle As IntPtr, _
                        ByVal ImpersonationLevel As Integer, _
                        ByRef DuplicateTokenHandle As IntPtr) As Integer

Declare Auto Function RevertToSelf Lib "advapi32.dll" () As Long
Declare Auto Function CloseHandle Lib "kernel32.dll" (ByVal handle As IntPtr) As Long


Public Sub Page_Load(ByVal s As Object, ByVal e As EventArgs)
    If impersonateValidUser("username", "domain", "password") Then
        'Inserte aquí el código que se ejecuta en el contexto de seguridad de un usuario específico.
        undoImpersonation()
    Else
        'Error en la suplantación. Por lo tanto, incluya aquí un mecanismo a prueba de errores.
    End If
End Sub

Private Function impersonateValidUser(ByVal userName As String, _
ByVal domain As String, ByVal password As String) As Boolean

    Dim tempWindowsIdentity As WindowsIdentity
    Dim token As IntPtr = IntPtr.Zero
    Dim tokenDuplicate As IntPtr = IntPtr.Zero
    impersonateValidUser = False

    If RevertToSelf() Then
        If LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, 
                     LOGON32_PROVIDER_DEFAULT, token) <> 0 Then
            If DuplicateToken(token, 2, tokenDuplicate) <> 0 Then
                tempWindowsIdentity = New WindowsIdentity(tokenDuplicate)
                impersonationContext = tempWindowsIdentity.Impersonate()
                If Not impersonationContext Is Nothing Then
                    impersonateValidUser = True
                End If
            End If
        End If
    End If
    If Not tokenDuplicate.Equals(IntPtr.Zero) Then
        CloseHandle(tokenDuplicate)
    End If
    If Not token.Equals(IntPtr.Zero) Then
        CloseHandle(token)
    End If
End Function

Private Sub undoImpersonation()
    impersonationContext.Undo()
End Sub
</script>
Visual C# .NET
<%@ Page Language="C#"%>
<%@ Import Namespace = "System.Web" %>
<%@ Import Namespace = "System.Web.Security" %>
<%@ Import Namespace = "System.Security.Principal" %>
<%@ Import Namespace = "System.Runtime.InteropServices" %>

<script runat=server>
public const int LOGON32_LOGON_INTERACTIVE = 2;
public const int LOGON32_PROVIDER_DEFAULT = 0;

WindowsImpersonationContext impersonationContext; 

[DllImport("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName, 
	String lpszDomain,
	String lpszPassword,
	int dwLogonType, 
	int dwLogonProvider,
	ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern int DuplicateToken(IntPtr hToken, 
	int impersonationLevel,  
	ref IntPtr hNewToken);
                          
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool RevertToSelf();

[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
public static extern  bool CloseHandle(IntPtr handle);

public void Page_Load(Object s, EventArgs e)
{
	if(impersonateValidUser("username", "domain", "password"))
	{
		//Inserte aquí el código que se ejecuta en el contexto de seguridad de un usuario específico.
		undoImpersonation();
	}
	else
	{
		//Error en la suplantación. Por lo tanto, incluya aquí un mecanismo a prueba de errores.
	}
}

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;
}

private void undoImpersonation()
{
	impersonationContext.Undo();
}
</script>
Visual J# .NET
<%@ Page language="VJ#" %>
<%@ Import Namespace="System.Web" %>
<%@ Import Namespace="System.Web.Security" %>
<%@ Import Namespace="System.Security.Principal" %>
<%@ Import Namespace="System.Runtime.InteropServices" %>

<script runat=server>
public static int LOGON32_LOGON_INTERACTIVE = 2;
public static int LOGON32_PROVIDER_DEFAULT = 0;

WindowsImpersonationContext impersonationContext; 

/** @attribute DllImport("advapi32.dll") */ 
public static native int LogonUserA(String lpszUserName, 
	String lpszDomain, 
	String lpszPassword,
	int dwLogonType, 
	int dwLogonProvider, 
	System.IntPtr[] phToken);

/** @attribute DllImport("advapi32.dll",
 CharSet=CharSet.Auto, SetLastError=true) */ 
public static native int DuplicateToken(System.IntPtr hToken,
	int impersonationLevel,
	System.IntPtr[] hNewToken);

/** @attribute DllImport("kernel32.dll",CharSet=CharSet.Auto) */ 
public static native  boolean CloseHandle(System.IntPtr[] handle);


/** @attribute DllImport("advapi32.dll",
 	 CharSet=CharSet.Auto,SetLastError=true) */	 
public static native boolean RevertToSelf();

public void Page_Load(Object s, System.EventArgs e)
{
	if(impersonateValidUser("username", "domain", "password"))
	{
		//Inserte aquí el código que se ejecuta en el contexto de seguridad de un usuario específico.
		undoImpersonation();
	}
	else
	{
		//Error en la suplantación. Por lo tanto, incluya aquí un mecanismo a prueba de errores.
	}
}

private boolean impersonateValidUser(String userName, String domain, String password)
{
	WindowsIdentity tempWindowsIdentity;
	System.IntPtr[] token = new System.IntPtr[1];
	System.IntPtr[] tokenDuplicate = new System.IntPtr[1];

	if(RevertToSelf())
	{
		if(LogonUserA(userName, domain, password, LOGON32_LOGON_INTERACTIVE, 
			LOGON32_PROVIDER_DEFAULT, token) != 0)
		{
			if(DuplicateToken(token[0], 2, tokenDuplicate) != 0) 
			{
				tempWindowsIdentity = new WindowsIdentity(tokenDuplicate[0]);
				impersonationContext = tempWindowsIdentity.Impersonate();
				if (impersonationContext != null)
				{
					CloseHandle(tokenDuplicate);
					CloseHandle(token);
					return true;
				}				
			}			
		} 
	}
	if(!token[0].Equals(System.IntPtr.Zero))
		CloseHandle(token);
	if(!tokenDuplicate[0].Equals(System.IntPtr.Zero))
		CloseHandle(tokenDuplicate);
	return false;

}

private void undoImpersonation()
{
	impersonationContext.Undo();
}
</script>
				
Nota: la identidad del proceso que suplanta a un usuario específico en el subproceso debe tener el privilegio "Actuar como parte del sistema operativo" si el proceso Aspnet_wp.exe se ejecuta en un equipo basado en Microsoft Windows 2000. El privilegio "Actuar como parte del sistema operativo" no se requiere si el proceso Aspnet_wp.exe se ejecuta en un equipo basado en Windows XP o en un equipo basado en Windows Server 2003. De manera predeterminada, el proceso Aspnet_wp.exe se ejecuta bajo una cuenta de equipo llamada ASPNET. Sin embargo, esta cuenta no tiene los privilegios necesarios para suplantar a un usuario específico. Recibirá un mensaje de error si intenta suplantar a un usuario específico. .

Como solución alternativa para este problema, utilice uno de los métodos siguientes:
  • Conceder el privilegio "Actuar como parte del sistema operativo" a la cuenta ASPNET.

    Nota: no se recomienda este método para solucionar el problema.
  • Cambie la cuenta que ejecuta el proceso Aspnet_wp.exe en la cuenta Sistema en la sección de configuración <processModel> del archivo Machine.config

Referencias

Para obtener información adicional acerca de la seguridad de ASP.NET, haga clic en el número de artículo siguiente para verlo en Microsoft Knowledge Base:
306590 Introducción a la seguridad de ASP.NET
Nota: es un artículo de "PUBLICACIÓN RÁPIDA" creado directamente por la organización de soporte técnico de Microsoft. La información aquí contenida se proporciona como está, como respuesta a problemas que han surgido. Como consecuencia de la rapidez con la que lo hemos puesto disponible, los materiales podrían incluir errores tipográficos y pueden ser revisados en cualquier momento sin previo aviso. Vea las Condiciones de uso para otras consideraciones

Propiedades

Id. de artículo: 306158 - Última revisión: martes, 04 de febrero de 2014 - Versión: 1.0
La información de este artículo se refiere a:
  • Microsoft ASP.NET 1.0
  • Microsoft ASP.NET 1.1
  • Microsoft Visual Basic .NET 2002 Standard Edition
  • Microsoft Visual Basic .NET 2003 Standard Edition
  • Microsoft Visual C# .NET 2002 Standard Edition
  • Microsoft Visual C# .NET 2003 Standard Edition
  • Microsoft Visual J# .NET 2003 Standard Edition
Palabras clave: 
kbinfo kbsecurity KB306158

Enviar comentarios

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com