Cómo autenticar en Active Directory mediante la autenticación de formularios y Visual Basic .NET

Resumen

Este artículo paso a paso describe cómo una aplicación ASP.NET puede utilizar autenticación de formularios para permitir a los usuarios para autenticarse en Active Directory utilizando el protocolo ligero de acceso a directorios (LDAP).

Una vez que el usuario se autentica y redirige, puede utilizar el método Application_AuthenticateRequest del archivo Global.asax para almacenar un objeto GenericPrincipal en la propiedad HttpContext.User que fluye a través de la solicitud.

Crear una aplicación Web ASP.NET en Visual Basic .NET

Siga estos pasos para crear una nueva aplicación Web ASP.NET denominada FormsAuthAd en Visual Basic .NET:
  1. Inicie Microsoft Visual Studio. NET.
  2. En el menú archivo, elija nuevo y, a continuación, haga clic en proyecto.
  3. Haga clic en Proyectos de Visual Basic en Tipos de proyectoy, a continuación, en plantillas, haga clic en Aplicación Web de ASP.NET .
  4. En el cuadro ubicación , escriba http://<servername>/FormsAuthAd (reemplazando http://localhost si está utilizando el servidor local (con el fin de tener http://localhost/FormsAuthAdy, a continuación, haga clic en Aceptar.
  5. Haga clic en el nodo referencias en el Explorador de soluciones y, a continuación, haga clic en Agregar referencia.
  6. En la ficha de .NET en el cuadro de diálogo Agregar referencia , haga clic en System.DirectoryServices.dll, haga clic en Seleccionar y, a continuación, haga clic en Aceptar.

Escriba el código de autenticación

Siga estos pasos para crear un nuevo archivo de clase denominado LdapAuthentication.vb:
  1. En el Explorador de soluciones, haga clic en el nodo del proyecto, elija Agregar y, a continuación, haga clic en Agregar nuevo elemento.
  2. En plantillas, haga clic en clase .
  3. Escriba LdapAuthentication.vb en el cuadro nombre y, a continuación, haga clic en Abrir.
  4. Reemplace el código existente en el archivo LdapAuthentication.vb con el código siguiente:
    Imports SystemImports System.Text
    Imports System.Collections
    Imports System.DirectoryServices

    Namespace FormsAuth
    Public Class LdapAuthentication

    Dim _path As String
    Dim _filterAttribute As String

    Public Sub New(ByVal path As String)
    _path = path
    End Sub

    Public Function IsAuthenticated(ByVal domain As String, ByVal username As String, ByVal pwd As String) As Boolean

    Dim domainAndUsername As String = domain & "\" & username
    Dim entry As DirectoryEntry = New DirectoryEntry(_path, domainAndUsername, pwd)

    Try
    'Bind to the native AdsObject to force authentication.
    Dim obj As Object = entry.NativeObject
    Dim search As DirectorySearcher = New DirectorySearcher(entry)

    search.Filter = "(SAMAccountName=" & username & ")"
    search.PropertiesToLoad.Add("cn")
    Dim result As SearchResult = search.FindOne()

    If (result Is Nothing) Then
    Return False
    End If

    'Update the new path to the user in the directory.
    _path = result.Path
    _filterAttribute = CType(result.Properties("cn")(0), String)

    Catch ex As Exception
    Throw New Exception("Error authenticating user. " & ex.Message)
    End Try

    Return True
    End Function

    Public Function GetGroups() As String
    Dim search As DirectorySearcher = New DirectorySearcher(_path)
    search.Filter = "(cn=" & _filterAttribute & ")"
    search.PropertiesToLoad.Add("memberOf")
    Dim groupNames As StringBuilder = New StringBuilder()

    Try
    Dim result As SearchResult = search.FindOne()
    Dim propertyCount As Integer = result.Properties("memberOf").Count

    Dim dn As String
    Dim equalsIndex, commaIndex

    Dim propertyCounter As Integer

    For propertyCounter = 0 To propertyCount - 1
    dn = CType(result.Properties("memberOf")(propertyCounter), String)

    equalsIndex = dn.IndexOf("=", 1)
    commaIndex = dn.IndexOf(",", 1)
    If (equalsIndex = -1) Then
    Return Nothing
    End If

    groupNames.Append(dn.Substring((equalsIndex + 1), (commaIndex - equalsIndex) - 1))
    groupNames.Append("|")
    Next

    Catch ex As Exception
    Throw New Exception("Error obtaining group names. " & ex.Message)
    End Try

    Return groupNames.ToString()
    End Function
    End Class
    End Namespace



Explicación del código

El código de autenticación acepta un dominio, un nombre de usuario, una contraseña y una ruta de acceso al árbol de Active Directory. Este código utiliza el proveedor de directorio LDAP.
Autenticación de usuario
El código de la página Logon.aspx llama al método LdapAuthentication.IsAuthenticated y pasa las credenciales que se recopilan desde el usuario. A continuación, se crea un objeto DirectoryEntry con la ruta de acceso del árbol del directorio, el nombre de usuario y la contraseña. El nombre de usuario debe ser en el formato "dominio\usuario". A continuación, el objeto DirectoryEntry intenta forzar al enlace de AdsObject obteniendo la propiedad NativeObject . Si lo consigue, el atributo CN del usuario se obtiene creando un objeto DirectorySearcher y filtrando SAMAccountName. Una vez autenticado el usuario, el método IsAuthenticated devuelve true.

Nota: Cuando se utiliza LDAP para enlazar a un objeto de Active Directory, se utilizan los puertos TCP. Aumento del uso de LDAP con el espacio de nombres System.DirectoryServices puede utilizar todos los puertos TCP que están disponibles. Puede reducir la carga TCP mediante la reutilización de la conexión que utiliza para autenticar el usuario.
Grupos de usuarios
Para obtener una lista de grupos a los que pertenece el usuario, este código llama al método LdapAuthentication.GetGroups . El método LdapAuthentication.GetGroups Obtiene una lista de grupos de seguridad y de distribución que pertenece el usuario, cree un objeto DirectorySearcher y filtrando según el atributo memberOf . Este método devuelve una lista de grupos que se separa mediante canalizaciones (|).

Observe que el método LdapAuthentication.GetGroups manipula y trunca cadenas. Esto reduce la longitud de la cadena que se almacena en la cookie de autenticación. Si la cadena no se trunca, el formato de cada grupo aparece como sigue:
CN=...,...,DC=domain,DC=com
Esto puede crear una cadena muy larga. Si la longitud de esta cadena es mayor que la longitud de la cookie, la cookie de autenticación no puede crearse. Si esta cadena potencialmente puede ser mayor que la longitud de la cookie, desea almacenar la información del grupo en el objeto Cache de ASP.NET o en una base de datos. Como alternativa, es aconsejable cifrar la información del grupo y almacenar esta información en un campo de formulario oculto.

Escriba el código de Global.asax

El código en el archivo Global.asax proporciona un controlador de eventos Application_AuthenticateRequest . Este controlador de eventos recupera la cookie de autenticación de la colección Context.Request.Cookies , descifra la cookie y recupera la lista de grupos que se almacenará en la propiedad FormsAuthenticationTicket.UserData . Los grupos aparecen en una lista separada de tubería que se crea en la página Logon.aspx.

El código analiza la cadena en una matriz de cadenas para crear un objeto GenericPrincipal . Una vez creado el objeto GenericPrincipal , este objeto se coloca en la propiedad HttpContext.User .
  1. En el Explorador de soluciones, haga clic derecho en Global.asaxy, a continuación, haga clic en Ver código.
  2. Agregue el código siguiente en la parte superior del código, detrás del archivo Global.asax.vb:
    Imports System.Web.SecurityImports System.Security.Principal

  3. Reemplace el controlador de eventos vacío existente para el Application_AuthenticateRequest con el siguiente código:
    Sub Application_AuthenticateRequest(ByVal sender As Object, ByVal e As EventArgs)        ' Fires upon attempting to authenticate the use
    Dim cookieName As String = FormsAuthentication.FormsCookieName
    Dim authCookie As HttpCookie = Context.Request.Cookies(cookieName)

    If (authCookie Is Nothing) Then
    'There is no authentication cookie.
    Return
    End If

    Dim authTicket As FormsAuthenticationTicket = Nothing

    Try
    authTicket = FormsAuthentication.Decrypt(authCookie.Value)
    Catch ex As Exception
    'Write the exception to the Event Log.
    Return
    End Try

    If (authTicket Is Nothing) Then
    'Cookie failed to decrypt.
    Return
    End If

    'When the ticket was created, the UserData property was assigned a
    'pipe-delimited string of group names.
    Dim groups As String() = authTicket.UserData.Split(New Char() {"|"})

    'Create an Identity.
    Dim id As GenericIdentity = New GenericIdentity(authTicket.Name, "LdapAuthentication")

    'This principal flows throughout the request.
    Dim principal As GenericPrincipal = New GenericPrincipal(id, groups)

    Context.User = principal

    End Sub

Modificar el archivo Web.config

En esta sección, se configura el
formularios, el
autenticacióny la
elementos de autorización en el archivo Web.config. Con estos cambios, sólo los usuarios autenticados pueden tener acceso a la aplicación, y las solicitudes no autenticadas se redirigen a una página Logon.aspx. Puede modificar esta configuración para permitir que sólo determinados usuarios y grupos de acceso a la aplicación.

Reemplace el código existente en el archivo Web.config con el código siguiente:
<?xml version="1.0" encoding="utf-8" ?><configuration>    
<system.web>
<authentication mode="Forms">
<forms loginUrl="logon.aspx" name="adAuthCookie" timeout="60" path="/" >
</forms>
</authentication>
<authorization>
<deny users="?" />
<allow users="*" />
</authorization>
<identity impersonate="true" />
</system.web>
</configuration>

Observe el identity impersonate = "true" / elemento de configuración. Esto hace que ASP.NET suplantar la cuenta que está configurada como la cuenta anónima de servicios de Microsoft Internet Information Services (IIS). Como resultado de esta configuración, todas las solicitudes a esta aplicación se ejecutan bajo el contexto de seguridad de la cuenta configurada. El usuario proporciona credenciales para autenticarse en Active Directory, pero la cuenta que tiene acceso a Active Directory es la cuenta configurada. Para obtener más información, consulte la sección REFERENCIAS .

Configurar IIS para la autenticación anónima

Para configurar IIS para la autenticación anónima, siga estos pasos:
  1. En la consola de administración de servicios de Internet Information Server (IIS), haga clic en el nodo del directorio Virtual para "FormsAuthAd".
  2. Haga clic en las Propiedadesy, a continuación, haga clic en la ficha Seguridad de directorios .
  3. En control de autenticación y acceso anónimo, haga clic en Editar .
  4. Active la casilla de verificación Acceso anónimo .
  5. Hacer que la cuenta anónima para la aplicación de una cuenta que tenga permiso para Active Directory.
  6. Haga clic para desactivar la casilla de verificación Permitir que IIS controle las contraseñas .
La cuenta IUSR_nombre_equipo de forma predeterminada no tiene permiso para Active Directory.

Crear la página Logon.aspx

Siga estos pasos para crear un nuevo formulario Web de ASP.NET denominada Logon.aspx:
  1. En el Explorador de soluciones, haga clic en el nodo del proyecto, elija Agregar y, a continuación, haga clic en Agregar formulario Web.
  2. Escriba Logon.aspx en el cuadro nombre y, a continuación, haga clic en Abrir.
  3. En el Explorador de soluciones, haga clic derecho en Logon.aspxy, a continuación, haga clic en Diseñador de vistas.
  4. Haga clic en la ficha HTML en el diseñador.
  5. Reemplace el código existente con el código siguiente:
    <%@ Page language="vb" AutoEventWireup="true" %><%@ Import Namespace="FormsAuthAd.FormsAuth" %>
    <html>
    <body>
    <form id="Login" method="post" runat="server">
    <asp:Label ID="Label1" Runat="server">Domain:</asp:Label>
    <asp:TextBox ID="txtDomain" Runat="server"></asp:TextBox><br>
    <asp:Label ID="Label2" Runat="server">Username:</asp:Label>
    <asp:TextBox ID="txtUsername" Runat="server"></asp:TextBox><br>
    <asp:Label ID="Label3" Runat="server">Password:</asp:Label>
    <asp:TextBox ID="txtPassword" Runat="server" TextMode="Password"></asp:TextBox><br>
    <asp:Button ID="btnLogin" Runat="server" Text="Login" OnClick="Login_Click"></asp:Button><br>
    <asp:Label ID="errorLabel" Runat="server" ForeColor="#ff3300"></asp:Label><br>
    <asp:CheckBox ID="chkPersist" Runat="server" Text="Persist Cookie" />
    </form>
    </body>
    </html>
    <script runat="server">
    sub Login_Click(sender as object,e as EventArgs)
    Dim adPath as String = "LDAP://DC=..,DC=.." 'Path to your LDAP directory server
    Dim adAuth as LdapAuthentication = new LdapAuthentication(adPath)
    try
    if(true = adAuth.IsAuthenticated(txtDomain.Text, txtUsername.Text, txtPassword.Text)) then
    Dim groups as string = adAuth.GetGroups()

    'Create the ticket, and add the groups.
    Dim isCookiePersistent as boolean = chkPersist.Checked
    Dim authTicket as FormsAuthenticationTicket = new FormsAuthenticationTicket(1, _
    txtUsername.Text,DateTime.Now, DateTime.Now.AddMinutes(60), isCookiePersistent, groups)

    'Encrypt the ticket.
    Dim encryptedTicket as String = FormsAuthentication.Encrypt(authTicket)

    'Create a cookie, and then add the encrypted ticket to the cookie as data.
    Dim authCookie as HttpCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)

    if(isCookiePersistent = true) then
    authCookie.Expires = authTicket.Expiration
    end if
    'Add the cookie to the outgoing cookies collection.
    Response.Cookies.Add(authCookie)

    'You can redirect now.
    Response.Redirect(FormsAuthentication.GetRedirectUrl(txtUsername.Text, false))

    else
    errorLabel.Text = "Authentication did not succeed. Check user name and password."
    end if

    catch ex as Exception
    errorLabel.Text = "Error authenticating. " & ex.Message
    end try
    end sub
    </script>

  6. Modifique la ruta de acceso en la página Logon.aspx para apuntar a su servidor de directorio LDAP.
La página Logon.aspx es una página que recopila información de los usuario y llamar a métodos en la clase LdapAuthentication . Después el código autentica al usuario y obtiene una lista de grupos, el código realiza lo siguiente en este orden:
  • crea un objeto FormsAuthenticationTicket ;
  • cifra el vale;
  • Agrega el vale cifrado a una cookie;
  • Agrega la cookie a la colección HttpResponse.Cookies ;
  • redirige la solicitud a la dirección URL que se solicitó originalmente.

Modificar la página WebForm1.aspx

La página WebForm1.aspx es la página que se solicitó originalmente. Cuando el usuario solicita esta página, la solicitud se redirige a la página Logon.aspx. Después de autentica la solicitud, la solicitud se redirige a la página WebForm1.aspx.
  1. En el Explorador de soluciones, (ratón) en WebForm1.aspxy, a continuación, haga clic en Diseñador de vistas.
  2. Haga clic en la ficha HTML en el diseñador.
  3. Reemplace el código existente con el código siguiente:
    <%@ Page language="vb" AutoEventWireup="true" %><%@ Import Namespace="System.Security.Principal" %>
    <html>
    <body>
    <form id="Form1" method="post" runat="server">
    <asp:Label ID="lblName" Runat="server" /><br>
    <asp:Label ID="lblAuthType" Runat="server" />
    </form>
    </body>
    </html>
    <script runat="server">
    sub Page_Load(sender as object, e as EventArgs)
    lblName.Text = "Hello " + Context.User.Identity.Name & "."
    lblAuthType.Text = "You were authenticated using " & Context.User.Identity.AuthenticationType & "."
    end sub
    </script>

  4. Guarde todos los archivos y, a continuación, compile el proyecto.
  5. Solicite la página WebForm1.aspx. Observe que se le redirige a Logon.aspx.
  6. Escriba las credenciales de inicio de sesión y, a continuación, haga clic en Enviar. Cuando se redirigen a WebForm1.aspx, observe que aparece el nombre de usuario y que LdapAuthentication es el tipo de autenticación para la propiedad Context.User.Identity.AuthenticationType .
Nota: Microsoft recomienda que utilice el cifrado de Secure Sockets Layer (SSL) cuando se utiliza la autenticación de formularios. Esto es porque el usuario se identifica según la cookie de autenticación y cifrado SSL en esta aplicación impide que alguien pueda poner en peligro la cookie de autenticación y cualquier otra información importante que se transmiten.

Referencias

Para obtener más información, haga clic en los números de artículo siguientes para verlos en Microsoft Knowledge Base:
Introducción a la seguridad ASP.NET 306590

317012 identidad de proceso y solicitud en ASP.NET

306238 cómo implementar seguridad basada en funciones con autenticación basada en formularios en su aplicación ASP.NET mediante Visual Basic .NET

313091 cómo crear claves utilizando Visual Basic .NET para su uso en autenticación mediante formularios

313116 las solicitudes de autenticación de formularios no se dirigen a loginUrl página

Propiedades

Id. de artículo: 326340 - Última revisión: 9 ene. 2017 - Revisión: 1

Comentarios