Use autenticação windows em seu website usando forms authentication

Aprenda a autenticar contas usando windows authentication.

Introdução

No último mês eu trabalhei em uma pequena tarefa de autenticar uma conta windows usando forms
Authentication.O propósito dessa tarefa era facilitar o logon de nossos usuários usando qualquer
conta válida do windows.Foi uma tarefa interessante,que eu decidi compartilhar com vocês.

Requerimentos

A aplicação deve autenticar usuários windows,usando forms authentication e o usuario logado
na conta do windows não deve se incomodar tendo que fazer um novo login na aplicação.Ele
deve poder se logar com qualquer conta windows válida.

Solução

Nós devemos seguir os seguintes passos para atingir nosso objetivo:

-Configurar as seções Authorization e Authentication no web.config
-Criar uma página de login e executar a lógica para autenticar usando a conta do windows
-Se as credenciais são válidas no passo anterior,gerar um “token” de autenticação assim o
usario poderá navegar nas diferentes páginas da sua aplicação.

Vamos lá,

Configurar Authorization e Authentication no web.config

Nós precisamos usar Forms authentication.O usuario vai entrar com suas credenciais do windows
no formulario e nós iremos valida-los:

1.<authentication mode=”Forms”>
2.   <forms loginUrl=”login.aspx” name=”.ASPXFORMSAUTH”></forms>
3.</authentication>

Para restringir acesso de usuários não logados,modifique a seção authorization no web.config:

1.<authorization>
2.   <deny users=”?”/>
3.</authorization>

Criar uma página de login para executar a lógica para autenticar as credencias do usuário do windows.

Nós precisamos criar uma página de login,para pegar informações de usuario e senha do usuario
e valida-las.

Nós temos diferentes formas de validar credenciais do Windows.A maneira que eu escolhi foi
o método LogonUser() de uma API Win32 chamada Advapi32.dll

O método LogonUser() tentar logar um usuario na máquina local.Esse método recebe um nome de usuario
uma senha e outras informações como parâmetros e retorna um boolean indicando se o usuario foi
logado ou não.Se retornar true significa que usuarios e senhas estão corretos.

Para usar esse método na sua classe,inclua o seguinte namespace:

1.using System.Runtime.InteropServices;

Depois adicione a seguinte declaração no método com o atributo DLLImport:

1.[DllImport(“ADVAPI32.dll”, EntryPoint = “LogonUserW”, SetLastError = true,
2.   CharSet = CharSet.Auto)]
3.public static extern bool LogonUser(string lpszUsername, string lpszDomain,
4.    string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

De acordo com a documentção MSDN:

lpszUsername[in]: string que especifica o nome de usuario.Esse é o nome da conta do logon.
Se você usar o formato “user principal name”(UPN) User@DnsDomainName,o parâmetro lpzszDomain
deve ficar nulo.

lpszDomain [in,opcional]:especifica o nome do dominio ou servidor que contém a conta de usuario
especificada no lpszUsername.

lpszPassword [in]:especifica a senha para a conta de usuario passada no lpszUsername.

dwLogonType[in]:O tipo de operação de logon.

dwLogonProvider[in]:especicifa o provedor de logon.

phToken[out]:Um ponteiro para uma variavel que contém um “token” que representa o usuario especifico.

Gerar um token de autenticação,se as credenciais forem autenticadas

Se as credenciais forem autenticadas no método LogoUser() então nós precisamos gerar um “token”
para que o usuario possa navegar nas paginas autorizadas da aplicação.
FormsAuthentication.RedirectFromLoginPage() ou FormsAuthentication.SetAuthCookie() podem ser usados para isso.

Aqui o código do clique do botão btnLogin pra autenticar e gerar o token de autenticação.
Comentários irão lhe ajudar a enteder o código:

01.protected void btnLogin_Click(object sender, EventArgs e)
02.{
03.   // Extract domain name from provided DomainUsername e.g Domainname\Username
04.   string domainName = GetDomainName(txtUserName.Text);
05.   // Extract user name from provided DomainUsername e.g Domainname\Username
06.   string userName = GetUsername(txtUserName.Text);
07.        IntPtr token = IntPtr.Zero;
08. //userName, domainName and Password parameters are very obvious.
09. /* dwLogonType (3rd parameter): I used LOGON32_LOGON_INTERACTIVE, This logon type is
10. intended for users who will be interactively using the computer, such as a user being
11. logged on by a terminal server, remote shell, or similar process. This logon type has
12. the additional expense of caching logon information for disconnected operations. For
13. more details about this parameter please see http://msdn.microsoft.com/en-
14. us/library/aa378184(VS.85).aspx */

15. /* dwLogonProvider (4th parameter) : I used LOGON32_PROVIDER_DEFAUL, This provider
16. uses the standard logon provider for the system. The default security provider is
17. negotiate, unless you pass NULL for the domain name and the user name is not in UPN
18. format. In this case, the default provider is NTLM. For more details about this
19. parameter please see http://msdn.microsoft.com/en-us/library/aa378184(VS.85).aspx */

20. /* phToken (5th parameter): A pointer to a handle variable that receives a handle to
21. a token that represents the specified user. We can use this handler for impersonation
22. purpose. */

23.    bool result = LogonUser(userName, domainName, txtPassword.Text, 2, 0, ref token);
24.    if (result)
25.    {
26.       //If Sucessfully authenticated
27. /* When an unatuthenticated user try to visit any page of your application that is
28. only allowed to view by authenticated users then ASP.NET automatically redirect that
29. user to login form and add ReturnUrl query string parameter that contain the url of a
30. page that user want to visit, So that we can redirect the user to that page after
31. authenticated. FormsAuthentication.RedirectFromLoginPage() method not only redirect
32. the user to that page but also genrate an authentication token for that user. */

33.       if (string.IsNullOrEmpty(Request.QueryString[“ReturnUrl”]))
34.       {
35.          FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, false);
36.       }
37. /* If ReturnUrl query string parameter is not present , then we need to generate
38. authentication token and redirect the user to any page ( acording to your application
39. need). FormsAuthentication.SetAuthCookie() method will generate Authentication
40. token*/

41.       else
42.       {
43.          FormsAuthentication.SetAuthCookie(txtUserName.Text, false);
44.          Response.Redirect(“default.aspx”);
45.       }
46.   }
47.   else
48.   {
49.      //If not authenticated then display an error message

50.      Response.Write(“Invalid username or password.”);
51.   }
52.}

Lista 1: Login.aspx

<%@ Page Language=”C#” AutoEventWireup=”true” CodeFile=”Login.aspx.cs”
02.     Inherits=”Login” %>
03.<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
04. “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”&gt;
05.<html xmlns=”http://www.w3.org/1999/xhtml”&gt;
06.<head runat=”server”>
07.    <title>Windows Authentication Using Form Authentication</title>
08.    <style type=”text/css”>
09.        .style1
10.        {
11.            width: 100%;
12.        }
13.    </style>
14.</head>
15.<body>
16.    <form id=”form1″ runat=”server”>
17.    <div>
18.        <table>
19.            <tr>
20.                <td>
21.                    <asp:Label ID=”lblUserName” runat=”server”
22.                         Text=”User Name:”></asp:Label>
23.                </td>
24.                <td>
25.                    <asp:TextBox ID=”txtUserName” runat=”server”></asp:TextBox>
26.                </td>
27.            </tr>
28.            <tr>
29.                <td>
30.                    <asp:Label ID=”lblPassword” runat=”server”
31.                         Text=”Password:”></asp:Label>
32.                </td>
33.                <td>
34.                    <asp:TextBox ID=”txtPassword” runat=”server”></asp:TextBox>
35.                </td>
36.            </tr>
37.            <tr>
38.                <td>
39.                     </td>
40.                <td>
41.                    <asp:Button ID=”btnLogin” runat=”server” onclick=”btnLogin_Click”
42.                        Text=”Login” />
43.                </td>
44.            </tr>
45.        </table>
46.    </div>
47.    <p>
48.         </p>
49.    </form>
50.</body>
51.</html>

Lista 2: Login.aspx.cs

using System;
002.using System.Collections;
003.using System.Configuration;
004.using System.Data;
005.using System.Linq;
006.using System.Web;
007.using System.Web.Security;
008.using System.Web.UI;
009.using System.Web.UI.HtmlControls;
010.using System.Web.UI.WebControls;
011.using System.Web.UI.WebControls.WebParts;
012.using System.Runtime.InteropServices;
013.public partial class Login : System.Web.UI.Page
014.{
015.    [DllImport(“ADVAPI32.dll”, EntryPoint = “LogonUserW”, SetLastError = true,
016.       CharSet = CharSet.Auto)]
017.    public static extern bool LogonUser(string lpszUsername, string lpszDomain,
018.       string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken);
019.    /// <summary>
020.    /// Parses the string to pull the domain name out.
021.    /// </summary>
022.    /// <param name=”usernameDomain”>The string to parse that must contain the domain
023.    /// in either the domain\username or UPN format username@domain</param>
024.    /// <returns>The domain name or “” if not domain is found.</returns>

025.    public static string GetDomainName(string usernameDomain)
026.    {
027.        if (string.IsNullOrEmpty(usernameDomain))
028.        {
029.            throw (new ArgumentException(“Argument can’t be null.”,
030.               “usernameDomain”));
031.        }
032.        if (usernameDomain.Contains(“\\”))
033.        {
034.            int index = usernameDomain.IndexOf(“\\”);
035.            return usernameDomain.Substring(0, index);
036.        }
037.        else if (usernameDomain.Contains(“@”))
038.        {
039.            int index = usernameDomain.IndexOf(“@”);
040.            return usernameDomain.Substring(index + 1);
041.        }
042.        else
043.        {
044.            return “”;
045.        }
046.    }
047.    /// <summary>
048.    /// Parses the string to pull the user name out.
049.    /// </summary>
050.    /// <param name=”usernameDomain”>The string to parse that must contain the
051.    /// username in either the domain\username or UPN format username@domain</param>
052.    /// <returns>The username or the string if no domain is found.</returns>

053.    public static string GetUsername(string usernameDomain)
054.    {
055.        if (string.IsNullOrEmpty(usernameDomain))
056.        {
057.            throw (new ArgumentException(“Argument can’t be null.”,
058.               “usernameDomain”));
059.        }
060.        if (usernameDomain.Contains(“\\”))
061.        {
062.            int index = usernameDomain.IndexOf(“\\”);
063.            return usernameDomain.Substring(index + 1);
064.        }
065.        else if (usernameDomain.Contains(“@”))
066.        {
067.            int index = usernameDomain.IndexOf(“@”);
068.            return usernameDomain.Substring(0, index);
069.        }
070.        else
071.        {
072.            return usernameDomain;
073.        }
074.    }
075.protected void btnLogin_Click(object sender, EventArgs e)
076.{
077.   // Extract domain name from provided DomainUsername e.g Domainname\Username
078.      string domainName = GetDomainName(txtUserName.Text);
079.   // Extract user name from provided DomainUsername e.g Domainname\Username
080.      string userName = GetUsername(txtUserName.Text);
081.      IntPtr token = IntPtr.Zero;
082. //userName, domainName and Password parameters are very obvious.
083. /* dwLogonType (3rd parameter): I used LOGON32_LOGON_INTERACTIVE, This logon type is
084. intended for users who will be interactively using the computer, such as a user being
085. logged on by a terminal server, remote shell, or similar process. This logon type has
086. the additional expense of caching logon information for disconnected operations. For
087. more details about this parameter please see http://msdn.microsoft.com/en-
088. us/library/aa378184(VS.85).aspx */
089. /* dwLogonProvider (4th parameter) : I used LOGON32_PROVIDER_DEFAUL, This provider
090. uses the standard logon provider for the system. The default security provider is
091. negotiate, unless you pass NULL for the domain name and the user name is not in UPN
092. format. In this case, the default provider is NTLM. For more details about this
093. parameter please see http://msdn.microsoft.com/en-us/library/aa378184(VS.85).aspx */
094. /* phToken (5th parameter): A pointer to a handle variable that receives a handle to
095. a token that represents the specified user. We can use this handler for impersonation
096. purpose. */

097.    bool result = LogonUser(userName, domainName, txtPassword.Text, 2, 0, ref token);
098.    if (result)
099.    {
100.       //If Sucessfully authenticated
101. /* When an unatuthenticated user try to visit any page of your application that is
102. only allowed to view by authenticated users then ASP.NET automatically redirect that
103. user to login form and add ReturnUrl query string parameter that contain the url of a
104. page that user want to visit, So that we can redirect the user to that page after
105. authenticated. FormsAuthentication.RedirectFromLoginPage() method not only redirect
106. the user to that page but also genrate an authentication token for that user. */

107.       if (string.IsNullOrEmpty(Request.QueryString[“ReturnUrl”]))
108.       {
109.          FormsAuthentication.RedirectFromLoginPage(txtUserName.Text, false);
110.       }
111. /* If ReturnUrl query string parameter is not present , then we need to generate
112. authentication token and redirect the user to any page ( acording to your application
113. need). FormsAuthentication.SetAuthCookie() method will generate Authentication
114. token*/

115.       else
116.       {
117.          FormsAuthentication.SetAuthCookie(txtUserName.Text, false);
118.          Response.Redirect(“default.aspx”);
119.       }
120.   }
121.   else
122.   {
123.      //If not authenticated then display an error message
124.      Response.Write(“Invalid username or password.”);
125.   }
126.}

Espero que aproveitem a dica,até a próxima!

Anúncios