Certa vez, criei com sucesso um lote de contas de domínio com caixas de correio usando um programa Windows. No entanto, quando dei esse código a uma de minhas colegas (ela era responsável pelo desenvolvimento de aplicativos da Web) e o migrei para o asp.net, ele só conseguiu criar um domínio. conta, não é possível criar caixa de correio. Por que?
Consultamos um engenheiro da Microsoft e ele nos disse que isso se devia a permissões insuficientes do asp.net. Deveríamos simular o usuário no asp.net para que ele pudesse ser criado com sucesso.
Extraí artigos relevantes da Microsoft:
Representar uma conta ou usuário autenticado pelo IIS
Para representar um usuário autenticado do Microsoft Internet Information Services (IIS) quando cada solicitação é recebida para cada página em um aplicativo ASP.NET, você deve incluir no arquivo Web.config para este aplicativo a tag <identity> e defina o atributo personificar como verdadeiro. Por exemplo:
<identidade personificar="true" />
Representando um usuário específico para todas as solicitações para um aplicativo ASP.NET
Para representar um usuário específico para todas as solicitações em todas as páginas de um aplicativo ASP.NET, você pode especificar os atributos userName e password. Por exemplo:
<identity impersonate="true" userName="accountname" password="password" />
Nota: A identidade do processo que representa um usuário específico em um thread deve ter a permissão “Como parte do sistema operacional”. Por padrão, o processo Aspnet_wp.exe é executado em uma conta de computador chamada ASPNET. No entanto, esta conta não possui as permissões necessárias para representar um usuário específico. Se você tentar se passar por um usuário específico, uma mensagem de erro aparecerá.
Para resolver este problema, utilize um dos seguintes métodos:
?
Conceda à conta ASPNET (a conta com menos privilégios) a permissão "Agir como parte do sistema operativo".
Nota: Embora este método possa resolver o problema, a Microsoft não o recomenda.
•
Na seção de configuração <processModel> do arquivo Machine.config, altere a conta sob a qual o processo Aspnet_wp.exe é executado para a conta do sistema.
Representando um usuário autenticado no código
Para representar um usuário autenticado (User.Identity) somente ao executar uma parte específica do código, você pode usar o código a seguir. Este método requer que o ID do usuário de autenticação seja do tipo WindowsIdentity.
Visual Basic .NET
Dim personationContext As System.Security.Principal.WindowsImpersonationContext
Dim currentWindowsIdentity como System.Security.Principal.WindowsIdentity
currentWindowsIdentity = CType(User.Identity, System.Security.Principal.WindowsIdentity)
personificaçãoContext = currentWindowsIdentity.Impersonate()
'Insira aqui o seu código que é executado no contexto de segurança do usuário autenticado.
personificaçãoContext.Undo()
Visual C# .NET
System.Security.Principal.WindowsImpersonationContext impersonationContext;
personificaçãoContext =
((System.Security.Principal.WindowsIdentity)User.Identity).Impersonate();
//Insira aqui seu código que é executado no contexto de segurança do usuário autenticado.
personificaçãoContext.Undo();
Visual J# .NET
System.Security.Principal.WindowsImpersonationContext impersonationContext;
personificaçãoContext =
((System.Security.Principal.WindowsIdentity)get_User().get_Identity()).Impersonate();
//Insira aqui seu código que é executado no contexto de segurança do usuário autenticado.
personificaçãoContext.Undo();
Representando um usuário específico no código
Para representar um usuário específico somente ao executar partes específicas do seu código, use o seguinte código:
Visual Basic .NET
<%@ Page Language="VB" %>
<%@ Importar Namespace = "System.Web" %>
<%@ Importar Namespace = "System.Web.Security" %>
<%@ Importar Namespace = "System.Security.Principal" %>
<%@ Importar Namespace = "System.Runtime.InteropServices" %>
<script runat=servidor>
Dim LOGON32_LOGON_INTERACTIVE como inteiro = 2
Dim LOGON32_PROVIDER_DEFAULT como inteiro = 0
Dim personationContext como WindowsImpersonationContext
Declarar função LogonUserA Lib "advapi32.dll" (ByVal lpszUsername As String, _
ByVal lpszDomain As String, _
ByVal lpszPassword como string, _
ByVal dwLogonType como inteiro, _
ByVal dwLogonProvider como inteiro, _
ByRef phToken As IntPtr) Como Inteiro
Declarar função automática DuplicateToken Lib "advapi32.dll" (_
ByVal ExistingTokenHandle As IntPtr, _
ByVal ImpersonationLevel como inteiro, _
ByRef DuplicateTokenHandle As IntPtr) Como Inteiro
Declarar função automática RevertToSelf Lib "advapi32.dll"() As Long
Declarar função automática CloseHandle Lib "kernel32.dll" (manuseador ByVal como IntPtr) tão longo
Public Sub Page_Load(ByVal s As Object, ByVal e As EventArgs)
Se personificarValidUser("nome de usuário", "domínio", "senha") Então
'Insira aqui seu código que é executado no contexto de segurança de um usuário específico.
desfazerImpersonation()
Outro
'Sua representação falhou. Portanto, inclua um mecanismo à prova de falhas aqui.
Terminar se
Finalizar sub
Função privada personateValidUser (ByVal userName As String, _
Domínio ByVal como string, senha ByVal como string) como booleano
Dim tempWindowsIdentity como WindowsIdentity
Dim token As IntPtr = IntPtr.Zero
Dim tokenDuplicate As IntPtr = IntPtr.Zero
personificarValidUser = Falso
Se RevertToSelf() então
Se LogonUserA(nomedeusuário, domínio, senha, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, token) <> 0 Então
Se DuplicateToken(token, 2, tokenDuplicate) <> 0 Então
tempWindowsIdentity = Nova WindowsIdentity(tokenDuplicate)
personificaçãoContext = tempWindowsIdentity.Impersonate()
Se não personificaçãoContext não for nada, então
personificarValidUser = Verdadeiro
Terminar se
Terminar se
Terminar se
Terminar se
Se não for tokenDuplicate.Equals(IntPtr.Zero) Então
CloseHandle(tokenDuplicado)
Terminar se
Se não for token.Equals(IntPtr.Zero) Então
FecharHandle(token)
Terminar se
Função final
Sub privado desfazer representação()
personificaçãoContext.Undo()
Finalizar sub
</script>
Visual C# .NET
<%@ Page Language="C#"%>
<%@ Importar Namespace = "System.Web" %>
<%@ Importar Namespace = "System.Web.Security" %>
<%@ Importar Namespace = "System.Security.Principal" %>
<%@ Importar Namespace = "System.Runtime.InteropServices" %>
<script runat=servidor>
public const int LOGON32_LOGON_INTERACTIVE = 2;
público const int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext personificaçãoContext;
[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 personationLevel,
ref IntPtr hNewToken);
[DllImport("advapi32.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool RevertToSelf();
[DllImport("kernel32.dll", CharSet=CharSet.Auto)]
público estático extern bool CloseHandle (identificador IntPtr);
public void Page_Load(Object s, EventArgs e)
{
if(impersonateValidUser("nome de usuário", "domínio", "senha"))
{
//Insira aqui seu código que é executado no contexto de segurança de um usuário específico.
desfazerImpersonation();
}
outro
{
//Sua representação falhou. Portanto, inclua um mecanismo à prova de falhas aqui.
}
}
private bool personateValidUser (String userName, String domínio, String senha)
{
WindowsIdentity tempWindowsIdentity;
Token IntPtr = IntPtr.Zero;
IntPtr tokenDuplicate = IntPtr.Zero;
if(RevertToSelf())
{
if(LogonUserA(nomedeusuário, domínio, senha, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, token de referência) != 0)
{
if(DuplicateToken(token, 2, ref tokenDuplicate) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
personificaçãoContext = tempWindowsIdentity.Impersonate();
if (impersonationContext! = Nulo)
{
CloseHandle(token);
CloseHandle(tokenDuplicado);
retornar verdadeiro;
}
}
}
}
if(token!= IntPtr.Zero)
CloseHandle(token);
if(tokenDuplicate!=IntPtr.Zero)
CloseHandle(tokenDuplicado);
retornar falso;
}
private void desfazerImpersonation()
{
personificaçãoContext.Undo();
}
</script>
Visual J# .NET
<%@ Page idioma="VJ#" %>
<%@Importar Namespace="System.Web" %>
<%@ Importar Namespace="System.Web.Security" %>
<%@ Import Namespace="System.Security.Principal" %>
<%@ Import Namespace="System.Runtime.InteropServices" %>
<script runat=servidor>
público estático int LOGON32_LOGON_INTERACTIVE = 2;
público estático int LOGON32_PROVIDER_DEFAULT = 0;
WindowsImpersonationContext personificaçãoContext;
/** @attribute DllImport("advapi32.dll") */
público estático nativo int LogonUserA(String lpszUserName,
String lpszDomain,
String lpszPassword,
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,
int personationLevel,
System.IntPtr[] hNewToken);
/** @attribute DllImport("kernel32.dll",CharSet=CharSet.Auto) */
público estático nativo booleano CloseHandle(System.IntPtr[] handle);
/** @attribute DllImport("advapi32.dll",
CharSet=CharSet.Auto,SetLastError=true) */
público estático nativo booleano RevertToSelf();
public void Page_Load(Object s, System.EventArgs e)
{
if(impersonateValidUser("nome de usuário", "domínio", "senha"))
{
//Insira aqui seu código que é executado no contexto de segurança de um usuário específico.
desfazerImpersonation();
}
outro
{
//Sua representação falhou. Portanto, inclua um mecanismo à prova de falhas aqui.
}
}
personateValidUser booleano privado (String userName, String domínio, String senha)
{
WindowsIdentity tempWindowsIdentity;
System.IntPtr[] token = novo System.IntPtr[1];
System.IntPtr[] tokenDuplicate = new System.IntPtr[1];
if(RevertToSelf())
{
if(LogonUserA(nomedeusuário, domínio, senha, LOGON32_LOGON_INTERACTIVE,
LOGON32_PROVIDER_DEFAULT, token) != 0)
{
if(DuplicateToken(token[0], 2, tokenDuplicado) != 0)
{
tempWindowsIdentity = new WindowsIdentity(tokenDuplicate[0]);
personificaçãoContext = tempWindowsIdentity.Impersonate();
if (impersonationContext! = Nulo)
{
CloseHandle(tokenDuplicado);
CloseHandle(token);
retornar verdadeiro;
}
}
}
}
if(!token[0].Equals(System.IntPtr.Zero))
CloseHandle(token);
if(!tokenDuplicate[0].Equals(System.IntPtr.Zero))
CloseHandle(tokenDuplicado);
retornar falso;
}
private void desfazerImpersonation()
{
personificaçãoContext.Undo();
}
</script>
Nota: A identidade do processo que representa um usuário específico em um thread deve ter a permissão “Como parte do sistema operacional”. Por padrão, o processo Aspnet_wp.exe é executado em uma conta de computador chamada ASPNET. No entanto, esta conta não possui as permissões necessárias para se passar por um usuário específico. Se você tentar se passar por um usuário específico, uma mensagem de erro aparecerá.
Para resolver este problema, utilize um dos seguintes métodos:
?
Conceda à conta ASPNET a permissão "Agir como parte do sistema operativo".
•
Na seção de configuração <processModel> do arquivo Machine.config, altere a conta sob a qual o processo Aspnet_wp.exe é executado para a conta do sistema.