Una vez creé con éxito un lote de cuentas de dominio con buzones de correo usando un programa de Windows. Sin embargo, cuando le di este código a una de mis colegas (ella era responsable del desarrollo de aplicaciones web) y lo migré a asp.net, solo pudo crear un dominio. cuenta, no se puede crear el buzón. ¿Por qué?
Consultamos a un ingeniero de Microsoft y nos dijo que esto se debía a permisos insuficientes de asp.net. Deberíamos simular el usuario en asp.net para que se pueda crear correctamente.
Extraje artículos relevantes de Microsoft:
Suplantar una cuenta o usuario autenticado de IIS
Para suplantar a un usuario autenticado de Microsoft Internet Information Services (IIS) cuando se recibe cada solicitud para cada página en una aplicación ASP.NET, debe incluir la etiqueta <identity> en el archivo Web.config de esta aplicación. y establezca el atributo de suplantación en verdadero. Por ejemplo:
<identidad suplantar="verdadero" />
Suplantar a un usuario específico para todas las solicitudes a una aplicación ASP.NET
Para suplantar a un usuario específico para todas las solicitudes en todas las páginas de una aplicación ASP.NET, puede especificar el atributo de nombre de usuario y contraseña. Por ejemplo:
<identidad impersonate="true" nombre de usuario="nombre de cuenta" contraseña="contraseña" />
Nota: La identidad del proceso que se hace pasar por un usuario específico en un hilo debe tener el permiso "Como parte del sistema operativo". De forma predeterminada, el proceso Aspnet_wp.exe se ejecuta en una cuenta de computadora llamada ASPNET. Sin embargo, esta cuenta no tiene los permisos necesarios para hacerse pasar por un usuario específico. Si intenta hacerse pasar por un usuario específico, aparecerá un mensaje de error.
Para resolver este problema, utilice uno de los métodos siguientes:
•
Otorgue a la cuenta ASPNET (la cuenta con menos privilegios) el permiso "Actuar como parte del sistema operativo".
Nota: Aunque este método puede resolver el problema, Microsoft no lo recomienda.
•
En la sección de configuración <processModel> del archivo Machine.config, cambie la cuenta bajo la cual se ejecuta el proceso Aspnet_wp.exe a la cuenta del Sistema.
Hacerse pasar por un usuario autenticado en el código
Para hacerse pasar por un usuario autenticado (User.Identity) solo cuando se ejecuta una parte específica del código, puede utilizar el siguiente código. Este método requiere que el ID de usuario de autenticación sea del tipo WindowsIdentity.
Visual Basic .NET
Dim impersonationContext como System.Security.Principal.WindowsImpersonationContext
Atenuar currentWindowsIdentity como System.Security.Principal.WindowsIdentity
currentWindowsIdentity = CType(Usuario.Identidad, Sistema.Seguridad.Principal.WindowsIdentidad)
impersonationContext = currentWindowsIdentity.Impersonate()
'Inserte aquí su código que se ejecuta bajo el contexto de seguridad del usuario que se autentica.
personationContext.Undo()
Visual C# .NET
System.Security.Principal.WindowsImpersonationContext impersonationContext;
contexto de suplantación =
((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
//Inserte aquí su código que se ejecuta bajo el contexto de seguridad del usuario que se autentica.
personationContext.Undo();
Visual J# .NET
System.Security.Principal.WindowsImpersonationContext impersonationContext;
contexto de suplantación =
((System.Security.Principal.WindowsIdentity)get_User().get_Identity()).Impersonate();
//Inserte aquí su código que se ejecuta bajo el contexto de seguridad del usuario que se autentica.
personationContext.Undo();
Suplantar a un usuario específico en el código
Para suplantar a un usuario específico solo cuando ejecuta partes específicas de su código, use el siguiente código:
Visual Basic .NET
<%@ Page Language="VB" %>
<%@ Importar espacio de nombres = "System.Web" %>
<%@ Importar espacio de nombres = "System.Web.Security" %>
<%@ Importar espacio de nombres = "System.Security.Principal" %>
<%@ Importar espacio de nombres = "System.Runtime.InteropServices" %>
<script runat=servidor>
Atenuar LOGON32_LOGON_INTERACTIVE como entero = 2
Atenuar LOGON32_PROVIDER_DEFAULT como entero = 0
Dim personationContext Como WindowsImpersonationContext
Declarar función LogonUserA Lib "advapi32.dll" (ByVal lpszUsername como cadena, _
ByVal lpszDomain como cadena, _
ByVal lpszContraseña como cadena, _
ByVal dwLogonType Como entero, _
ByVal dwLogonProvider como entero, _
ByRef phToken como IntPtr) como entero
Declarar función automática DuplicateToken Lib "advapi32.dll" (_
ByVal ExistingTokenHandle como IntPtr, _
ByVal Nivel de suplantación como entero, _
ByRef DuplicateTokenHandle como IntPtr) como entero
Declarar función automática RevertToSelf Lib "advapi32.dll" () siempre y cuando
Declarar la función automática CloseHandle Lib "kernel32.dll" (identificador ByVal como IntPtr) durante todo el tiempo
Public Sub Page_Load(ByVal s como objeto, ByVal e como EventArgs)
Si impersonateValidUser ("nombre de usuario", "dominio", "contraseña") Entonces
'Inserte aquí su código que se ejecuta bajo el contexto de seguridad de un usuario específico.
deshacer suplantación()
Demás
'Su suplantación falló. Por lo tanto, incluya aquí un mecanismo de seguridad.
Terminar si
Subtítulo final
Función privada impersonateValidUser (ByVal nombre de usuario como cadena, _
Dominio ByVal como cadena, contraseña ByVal como cadena) como booleano
Temperatura tenueWindowsIdentity como WindowsIdentity
Token tenue como IntPtr = IntPtr.Zero
Dim tokenDuplicate As IntPtr = IntPtr.Zero
suplantarValidUser = Falso
Si RevertToSelf() Entonces
Si LogonUserA(nombre de usuario, dominio, contraseña, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, token) <> 0 Entonces
Si DuplicateToken(token, 2, tokenDuplicate) <> 0 Entonces
tempWindowsIdentity = Nueva identidad de Windows (tokenDuplicate)
impersonationContext = tempWindowsIdentity.Impersonate()
Si no el contexto de suplantación no es nada, entonces
suplantarValidUser = Verdadero
Terminar si
Terminar si
Terminar si
Terminar si
Si no es tokenDuplicate.Equals(IntPtr.Zero) Entonces
CloseHandle(tokenDuplicate)
Terminar si
Si no es token.Equals(IntPtr.Zero) Entonces
Cerrar identificador (token)
Terminar si
Función final
Sub privado deshacer suplantación ()
personationContext.Undo()
Subtítulo final
</script>
Visual C# .NET
<%@ Idioma de página="C#"%>
<%@ Importar espacio de nombres = "System.Web" %>
<%@ Importar espacio de nombres = "System.Web.Security" %>
<%@ Importar espacio de nombres = "System.Security.Principal" %>
<%@ Importar espacio de nombres = "System.Runtime.InteropServices" %>
<script runat=servidor>
constante pública int LOGON32_LOGON_INTERACTIVE = 2;
constante pública int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext suplantaciónContext;
[DllImport ("advapi32.dll")]
public static extern int LogonUserA(String lpszUserName,
Cadena lpszDomain,
Cadena lpszContraseña,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
público estático externo int DuplicateToken(IntPtr hToken,
nivel de suplantación int,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
bool externo estático público RevertToSelf();
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
bool externo estático público CloseHandle (identificador IntPtr);
Public void Page_Load (Objeto s, EventArgs e)
{
if(impersonateValidUser("nombre de usuario", "dominio", "contraseña"))
{
//Inserte aquí su código que se ejecuta bajo el contexto de seguridad de un usuario específico.
deshacerSuplantación();
}
demás
{
//Su suplantación falló. Por lo tanto, incluya aquí un mecanismo a prueba de fallas.
}
}
bool privado impersonateValidUser (nombre de usuario de cadena, dominio de cadena, contraseña de cadena)
{
WindowsIdentity tempWindowsIdentity;
Token IntPtr = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
si(RevertirASelf())
{
if(LogonUserA(nombre de usuario, dominio, contraseña, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, token de referencia) != 0)
{
if(DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = nueva WindowsIdentity(tokenDuplicate);
impersonationContext = tempWindowsIdentity.Impersonate();
si (suplantaciónContexto! = nulo)
{
CloseHandle(token);
CloseHandle(tokenDuplicate);
devolver verdadero;
}
}
}
}
si (token! = IntPtr.Zero)
CloseHandle(token);
si(tokenDuplicate!=IntPtr.Zero)
CloseHandle(tokenDuplicate);
devolver falso;
}
deshacer suplantación de vacío privado ()
{
personationContext.Undo();
}
</script>
Visual J# .NET
<%@ Idioma de página="VJ#" %>
<%@ Importar espacio de nombres="System.Web" %>
<%@ Importar espacio de nombres="System.Web.Security" %>
<%@ Importar espacio de nombres="System.Security.Principal" %>
<%@ Importar espacio de nombres="System.Runtime.InteropServices" %>
<script runat=servidor>
público estático int LOGON32_LOGON_INTERACTIVE = 2;
int estático público LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext suplantaciónContext;
/** @attribute DllImport("advapi32.dll") */
público estático nativo int LogonUserA(String lpszUserName,
Cadena lpszDomain,
Cadena lpszContraseña,
int dwLogonType,
int dwLogonProvider,
System.IntPtr[]phToken);
/** @attribute DllImport("advapi32.dll",
CharSet=CharSet.Auto, SetLastError=true) */
público estático nativo int DuplicateToken(System.IntPtr hToken,
nivel de suplantación int,
System.IntPtr[] hNewToken);
/** @attribute DllImport("kernel32.dll",CharSet=CharSet.Auto) */
CloseHandle booleano nativo estático público (identificador System.IntPtr []);
/** @attribute DllImport("advapi32.dll",
CharSet=CharSet.Auto,SetLastError=true) */
booleano nativo estático público RevertToSelf();
Page_Load vacío público (Objeto s, System.EventArgs e)
{
if(impersonateValidUser("nombre de usuario", "dominio", "contraseña"))
{
//Inserte aquí su código que se ejecuta bajo el contexto de seguridad de un usuario específico.
deshacerSuplantación();
}
demás
{
//Su suplantación falló. Por lo tanto, incluya aquí un mecanismo a prueba de fallas.
}
}
impersonateValidUser booleano privado (nombre de usuario de cadena, dominio de cadena, contraseña de cadena)
{
WindowsIdentity tempWindowsIdentity;
System.IntPtr[] token = nuevo System.IntPtr[1];
System.IntPtr[] tokenDuplicate = nuevo System.IntPtr[1];
si(RevertToSelf())
{
if(LogonUserA(nombre de usuario, dominio, contraseña, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, token) != 0)
{
if(DuplicateToken(token[0], 2, tokenDuplicate) != 0)
{
tempWindowsIdentity = nueva WindowsIdentity(tokenDuplicate[0]);
impersonationContext = tempWindowsIdentity.Impersonate();
si (suplantaciónContexto! = nulo)
{
CloseHandle(tokenDuplicate);
CloseHandle(token);
devolver verdadero;
}
}
}
}
if(!token[0].Equals(System.IntPtr.Zero))
CloseHandle(token);
if(!tokenDuplicate[0].Equals(System.IntPtr.Zero))
CloseHandle(tokenDuplicate);
devolver falso;
}
deshacer suplantación de vacío privado ()
{
personationContext.Undo();
}
</script>
Nota: La identidad del proceso que se hace pasar por un usuario específico en un hilo debe tener el permiso "Como parte del sistema operativo". De forma predeterminada, el proceso Aspnet_wp.exe se ejecuta en una cuenta de computadora llamada ASPNET. Sin embargo, esta cuenta no tiene los permisos necesarios para hacerse pasar por un usuario específico. Si intenta hacerse pasar por un usuario específico, aparecerá un mensaje de error.
Para resolver este problema, utilice uno de los métodos siguientes:
?
Conceda a la cuenta ASPNET el permiso "Actuar como parte del sistema operativo".
•
En la sección de configuración <processModel> del archivo Machine.config, cambie la cuenta bajo la cual se ejecuta el proceso Aspnet_wp.exe a la cuenta del Sistema.