"Representação" no espaço .NET geralmente significa executar código em uma conta de usuário específica. É um conceito um pouco separado do que obter acesso a essa conta de usuário por meio de um nome de usuário e senha, embora essas duas idéias sejam frequentemente combinadas. Descreverei os dois e depois explicarei como usar minha biblioteca SimpleImpersonation , que os utiliza internamente.
Representação
As APIs para representação são fornecidas no .NET por meio do System.Security.Principal
namespace:
O código mais recente (.NET 4.6+, .NET Core etc.) geralmente deve ser usado WindowsIdentity.RunImpersonated
, o que aceita um identificador para o token da conta do usuário e, em seguida, um Action
ou Func<T>
para o código executar.
WindowsIdentity.RunImpersonated(tokenHandle, () =>
{
// do whatever you want as this user.
});
ou
var result = WindowsIdentity.RunImpersonated(tokenHandle, () =>
{
// do whatever you want as this user.
return result;
});
O código mais antigo usava o WindowsIdentity.Impersonate
método para recuperar um WindowsImpersonationContext
objeto. Esse objeto é implementado IDisposable
, portanto geralmente deve ser chamado de um using
bloco.
using (WindowsImpersonationContext context = WindowsIdentity.Impersonate(tokenHandle))
{
// do whatever you want as this user.
}
Embora essa API ainda exista no .NET Framework, ela geralmente deve ser evitada e não está disponível no .NET Core ou no .NET Standard.
Acessando a conta do usuário
A API para usar um nome de usuário e senha para obter acesso a uma conta de usuário no Windows é LogonUser
- que é uma API nativa do Win32. No momento, não existe uma API .NET interna para chamá-la, portanto, é necessário recorrer à P / Invoke.
[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
internal static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);
Esta é a definição básica de chamada, no entanto, há muito mais a considerar para usá-la realmente na produção:
- Obtendo um identificador com o padrão de acesso "seguro".
- Fechar adequadamente os identificadores nativos
- Níveis de confiança de segurança de acesso ao código (CAS) (somente no .NET Framework)
- Passando
SecureString
quando você pode coletar um com segurança, pressionando as teclas do usuário.
A quantidade de código a ser escrito para ilustrar tudo isso está além do que deveria estar em uma resposta do StackOverflow, IMHO.
Uma abordagem combinada e mais fácil
Em vez de escrever tudo isso você mesmo, considere usar minha biblioteca SimpleImpersonation , que combina representação e acesso de usuário em uma única API. Funciona bem em bases de código modernas e antigas, com a mesma API simples:
var credentials = new UserCredentials(domain, username, password);
Impersonation.RunAsUser(credentials, logonType, () =>
{
// do whatever you want as this user.
});
ou
var credentials = new UserCredentials(domain, username, password);
var result = Impersonation.RunAsUser(credentials, logonType, () =>
{
// do whatever you want as this user.
return something;
});
Observe que é muito semelhante à WindowsIdentity.RunImpersonated
API, mas não requer que você saiba nada sobre identificadores de token.
Esta é a API da versão 3.0.0. Consulte o leia-me do projeto para obter mais detalhes. Observe também que uma versão anterior da biblioteca usava uma API com o IDisposable
padrão, semelhante a WindowsIdentity.Impersonate
. A versão mais recente é muito mais segura e ambas ainda são usadas internamente.