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

En este artículo se refiere a los siguientes espacios de nombres de biblioteca de clases de Microsoft.NET Framework:
  • System.Text
  • System.DirectoryServices
  • System.Security.Principal
  • System.Web.Security

Resumen

En este artículo paso a paso se muestra 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 C#.

Siga estos pasos para crear una nueva aplicación Web ASP.NET denominada FormsAuthAd en Visual .NET C#:
  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 C# en Tipos de proyectoy, a continuación, en plantillas, haga clic en Aplicación Web de ASP.NET .
  4. En el cuadro ubicación , reemplace WebApplication1 con FormsAuthAd.
  5. Haga clic en Aceptar.
  6. Haga clic en el nodo referencias en el Explorador de soluciones y, a continuación, haga clic en Agregar referencia.
  7. 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.cs:
  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.cs en el cuadro nombre y, a continuación, haga clic en Abrir.
  4. Reemplace el código existente en el archivo LdapAuthentication.cs con el código siguiente.
    using System;using System.Text;
    using System.Collections;
    using System.DirectoryServices;

    namespace FormsAuth
    {
    public class LdapAuthentication
    {
    private String _path;
    private String _filterAttribute;

    public LdapAuthentication(String path)
    {
    _path = path;
    }

    public bool IsAuthenticated(String domain, String username, String pwd)
    {
    String domainAndUsername = domain + @"\" + username;
    DirectoryEntry entry = new DirectoryEntry(_path, domainAndUsername, pwd);

    try
    {//Bind to the native AdsObject to force authentication.
    Object obj = entry.NativeObject;

    DirectorySearcher search = new DirectorySearcher(entry);

    search.Filter = "(SAMAccountName=" + username + ")";
    search.PropertiesToLoad.Add("cn");
    SearchResult result = search.FindOne();

    if(null == result)
    {
    return false;
    }

    //Update the new path to the user in the directory.
    _path = result.Path;
    _filterAttribute = (String)result.Properties["cn"][0];
    }
    catch (Exception ex)
    {
    throw new Exception("Error authenticating user. " + ex.Message);
    }

    return true;
    }

    public String GetGroups()
    {
    DirectorySearcher search = new DirectorySearcher(_path);
    search.Filter = "(cn=" + _filterAttribute + ")";
    search.PropertiesToLoad.Add("memberOf");
    StringBuilder groupNames = new StringBuilder();

    try
    {
    SearchResult result = search.FindOne();

    int propertyCount = result.Properties["memberOf"].Count;

    String dn;
    int equalsIndex, commaIndex;

    for(int propertyCounter = 0; propertyCounter < propertyCount; propertyCounter++)
    {
    dn = (String)result.Properties["memberOf"][propertyCounter];

    equalsIndex = dn.IndexOf("=", 1);
    commaIndex = dn.IndexOf(",", 1);
    if(-1 == equalsIndex)
    {
    return null;
    }

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

    }
    }
    catch(Exception ex)
    {
    throw new Exception("Error obtaining group names. " + ex.Message);
    }
    return groupNames.ToString();
    }
    }
    }

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.

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.

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, los exploradores pueden no aceptar la cookie de autenticación y se le redirigirá a la página de inicio de sesión. Sin embargo, si está en un entorno de múltiples dominios, tendrá que mantener el nombre de dominio con el nombre del grupo porque los grupos en dominios diferentes pueden tener el mismo nombre de grupo. Tiene que mantener el nombre de dominio para diferenciar un grupo de otro.

La mayoría de los exploradores admiten cookies de hasta 4096 bytes. Si esta cadena potencialmente puede superar 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 archivo Global.asax.cs código subyacente:
    using System.Web.Security;using System.Security.Principal;

  3. Reemplace el controlador de eventos vacío existente para el Application_AuthenticateRequest con el código siguiente.
    void Application_AuthenticateRequest(Object sender, EventArgs e){
    String cookieName = FormsAuthentication.FormsCookieName;
    HttpCookie authCookie = Context.Request.Cookies[cookieName];

    if(null == authCookie)
    {//There is no authentication cookie.
    return;
    }

    FormsAuthenticationTicket authTicket = null;

    try
    {
    authTicket = FormsAuthentication.Decrypt(authCookie.Value);
    }
    catch(Exception ex)
    {
    //Write the exception to the Event Log.
    return;
    }

    if(null == authTicket)
    {//Cookie failed to decrypt.
    return;
    }

    //When the ticket was created, the UserData property was assigned a
    //pipe-delimited string of group names.
    String[] groups = authTicket.UserData.Split(new char[]{'|'});

    //Create an Identity.
    GenericIdentity id = new GenericIdentity(authTicket.Name, "LdapAuthentication");

    //This principal flows throughout the request.
    GenericPrincipal principal = new GenericPrincipal(id, groups);

    Context.User = principal;

    }

Modificar el archivo Web.config

En esta sección, se configuran el < forms >, < autenticación >y los elementos < 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="10" 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 IIS, expanda el nodo de equipo para el servidor, expanda sitios Web, expanda sitio Web predeterminado, haga FormsAuthAdy, a continuación, haga clic en Propiedades.
  2. Haga clic en la Ficha seguridad de directorios y, a continuación, haga clic en Editar, bajo Control de autenticación y acceso anónimo.
  3. Hacer que la cuenta anónima para la aplicación de una cuenta que tenga permiso para Active Directory.
  4. Haga clic para desactivar la casilla de verificación Permitir que IIS controle las contraseñas.
  5. En la sección "Acceso autenticado", desactive la casilla de verificación "Autenticación de Windows integrada".
  6. Haga clic en Aceptar.
  7. Haga clic en aplicar
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="c#" AutoEventWireup="true" %><%@ Import Namespace="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>
    void Login_Click(Object sender, EventArgs e)
    {
    String adPath = "LDAP://corp.com"; //Fully-qualified Domain Name
    LdapAuthentication adAuth = new LdapAuthentication(adPath);
    try
    {
    if(true == adAuth.IsAuthenticated(txtDomain.Text, txtUsername.Text, txtPassword.Text))
    {
    String groups = adAuth.GetGroups();

    //Create the ticket, and add the groups.
    bool isCookiePersistent = chkPersist.Checked;
    FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(1, txtUsername.Text,
    DateTime.Now, DateTime.Now.AddMinutes(60), isCookiePersistent, groups);

    //Encrypt the ticket.
    String encryptedTicket = FormsAuthentication.Encrypt(authTicket);

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

    if(true == isCookiePersistent)
    authCookie.Expires = authTicket.Expiration;

    //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.";
    }
    }
    catch(Exception ex)
    {
    errorLabel.Text = "Error authenticating. " + ex.Message;
    }
    }
    </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 crea un objeto FormsAuthenticationTicket , cifra el vale, agrega el vale cifrado a una cookie, agrega la cookie a la colección HttpResponse.Cookies y, a continuación, 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="c#" 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>
    void Page_Load(Object sender, EventArgs e)
    {
    lblName.Text = "Hello " + Context.User.Identity.Name + ".";
    lblAuthType.Text = "You were authenticated using " + Context.User.Identity.AuthenticationType + ".";
    }
    </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.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

311495 cómo implementar seguridad basada en funciones con autenticación basada en formularios en su aplicación ASP.NET mediante Visual C#.

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 la página loginUrl

Propiedades

Id. de artículo: 316748 - Última revisión: 17 ene. 2017 - Revisión: 2

Comentarios