Dev (Back & Front)ARTIGO

Trabalhando com impersonate e web

Olá, pessoal,
depois de ter o privilégio de mais um ano de vida quero mostrar como usar o impersonate via web no seu aplicativo ou
no da empresa. Mas antes veja com atenção sobre o contexto que estou abordando
e desenvolvendo o software.

Referências:

  • Linguagem C#.NET
  • Ferramenta: Visual
    Studio .NET 2008
  • Framework 3.5
  • Plataforma:
    ASP.NET

Contexto 1

Tenho um servidor que está na internet,
ou seja, tem ip fixo, tem sites instalados, tem IIS instalado e configurado.
Tenho outro servidor que serve para uso interno, isto é, não está na internet,
mas está na mesma rede. Só tem IP interno e não tem externo e, para entrar
nele, preciso apenas de um usuário com permissão de acesso a determinada pasta.

Contexto 2

A aplicação que tenho hoje gera um pdf
com assinatura digital e joga o mesmo no servidor interno, ou seja, não tenho
acesso via web para acessar estes arquivos, no caso de querer visualizá-los
pela internet, browser ou outra ferramenta.

Contexto 3

Devido aos contextos 1 e 2, preciso usar
um usuário que tenha acesso à determinada pasta onde estão os arquivos. Lembrando
que estes artigos estão em um servidor interno e a minha aplicação web está em
um servidor na internet, na mesma rede.

Para ter este tipo de acesso, preciso
de um usuário da rede com permissão à pasta e assim conseguir mostrar os
arquivos pelo sistema web acessando com usuário local. Para acessar com o
usuário da rede é necessário fazer um impersonate.
Para quem não sabe, é usar um usuário específico para acessar determinado local
em vez de usar o usuário da web.

Depois de toda essa explicação, quero
mostrar passo a passo como fazer o impersonate
no sistema web com objetivo de acessar um determinado local com usuário
específico. Geralmente usamos isso em empresas.

Código

O primeiro passo é importar algumas
classes do framework .net. No meu caso estou usando a versão 3.5:

using System.Security;<br /><br />using System.Security.Principal;<br /><br />using System.Runtime;<br /><br />using System.Runtime.InteropServices;<br /><br />using System.Web;<br /><br />using System.Web.Security;

O segundo passo é usar algumas dll’s do
sistema operacional Windows para fazer este logon. Criei algumas constantes de
usuário, senha e domínio:

  #region "   Impersonate   " <br /><br />        [System.Runtime.InteropServices.DllImport("advapi32.dll")]<br />        public static extern int LogonUser(String lpszUserName,<br />            String lpszDomain,<br />            String lpszPassword,<br />            int dwLogonType,<br />            int dwLogonProvider,<br />            ref IntPtr phToken); <br /><br />        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]<br />        public static extern int DuplicateToken(IntPtr hToken,<br />            int impersonationLevel,<br />            ref IntPtr hNewToken);<br /><br />        [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]<br />        public static extern bool RevertToSelf();<br /><br />        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]<br />        public static extern bool CloseHandle(IntPtr handle);<br /><br />        const int LOGON32_PROVIDER_DEFAULT = 0;<br />        const int LOGON32_LOGON_INTERACTIVE = 2;<br /><br />        static WindowsImpersonationContext wic;<br />        const string User = "seu_usuario";<br />        const string Domain = "seu_dominio";<br />        const string Pwd = "sua_senha";<br /><br />        #endregion

O terceiro passo é criar um método que
loga utilizando as credenciais do usuário local, ou seja, aquele que coloquei
nas constantes. O método precisa passar alguns parâmetros de entrada. Resolvi
criar um método estático para não precisar criar um “new” ou uma nova
instância:

 static public bool ImpersonateValidUser(String userName, String domain, String password)<br />        {<br />            WindowsIdentity wi;<br />            IntPtr token = IntPtr.Zero;<br />            IntPtr tokenDuplicate = IntPtr.Zero; <br /><br />            if (RevertToSelf())<br />            {<br />                if (LogonUser(userName, domain, password, LOGON32_LOGON_INTERACTIVE,<br />                    LOGON32_PROVIDER_DEFAULT, ref token) != 0)<br />                {<br />                    if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)<br />                    {<br />                        wi = new WindowsIdentity(tokenDuplicate);<br />                        wic = wi.Impersonate();<br />                        if (wic != null)<br />                        {<br />                            CloseHandle(token);<br />                            CloseHandle(tokenDuplicate);<br />                            return true;<br />                        }<br />                    }<br />                }<br />            }<br />            if (token != IntPtr.Zero)<br />                CloseHandle(token);<br />            if (tokenDuplicate != IntPtr.Zero)<br />                CloseHandle(tokenDuplicate);<br />            return false;<br />        }

O quarto e último passo: usei o
Load_Page da página criada para fazer tudo que criamos anteriormente com poucas
linhas de código. Chamei o método (code 3) e usei a variável falando para usar
o usuário local e abrir o arquivo:

    if (ImpersonateValidUser(User, Domain, Pwd))<br />            {<br />                using (wic)<br />                {<br />                }<br />            } 

Note que usei as constantes de usuário,
domínio e senha, depois coloquei “using (wic)” que constitui da variável do
usuário logado localmente. Dentro do using (wic) coloquei o código que chama o
arquivo pdf dinamicamente e dessa forma o arquivo é mostrado sem qualquer
problema, veja na próxima imagem. 

Tudo que for escrito dentro do using
(wic) será feito com o usuário do impersonate.

 

Bom,
eu fico por aqui e espero que tenha entendido tudo sobre o artigo. Não
expliquei o que fiz dentro do método para não prolongar muito o texto. O
objetivo foi ser “objetivo”.

Qualquer dúvida
pode entrar em contato pelo site.

Com mais de 20 anos trabalhando no mercado de tecnologia. Mestre em Engenharia Elétrica voltada para o mundo mobile, com mais de 20 livros publicados e cerca de 700 artigos publicados com intuito de ajudar àqueles que querem aprender a programar (site, software, desktop, serviços, api e mobile). Site pessoal: https://www.mauriciojunior.net - MVP, MCAD, MCP Microsoft

Ver perfil