Información general sobre la autenticación de formularios (C#)

Por Scott Mitchell

Nota:

Desde que se escribió este artículo, los proveedores de ASP.NET Membership han sido reemplazados por ASP.NET Identity. Se recomienda encarecidamente actualizar las aplicaciones para usar la plataformaASP.NET Identity en lugar de los proveedores de pertenencia destacados en el momento en que se escribió este artículo. ASP.NET Identity tiene una serie de ventajas sobre el sistema de pertenencia ASP.NET, incluidas las siguientes:

  • Mejor rendimiento
  • Extensibilidad y capacidad de prueba mejoradas
  • Compatibilidad con OAuth, OpenID Connect y autenticación en dos fases
  • Compatibilidad con identidades basadas en notificaciones
  • Mejor interoperabilidad con ASP.Net Core

Descargar código o Descargar PDF

En este tutorial, pasaremos de mera discusión a implementación; en concreto, veremos la implementación de la autenticación de formularios. La aplicación web que empezamos a construir en este tutorial se seguirá basando en tutoriales posteriores, ya que pasamos de la autenticación de formularios simples a la pertenencia y los roles.

Consulte este vídeo para obtener más información sobre este tema: Uso de la autenticación de formularios básicos en ASP.NET.

Introducción

En el tutorial anterior se describieron las distintas opciones de autenticación, autorización y cuenta de usuario proporcionadas por ASP.NET. En este tutorial, pasaremos de mera discusión a implementación; en concreto, veremos la implementación de la autenticación de formularios. La aplicación web que empezamos a construir en este tutorial se seguirá basando en tutoriales posteriores, ya que pasamos de la autenticación de formularios simples a la pertenencia y los roles.

Este tutorial comienza con una visión detallada del flujo de trabajo de autenticación de formularios, un tema que hemos tocado en el tutorial anterior. Después, crearemos un sitio web ASP.NET a través del cual demostraremos los conceptos de autenticación de formularios. A continuación, configuraremos el sitio para que use la autenticación de formularios, crearemos una página de inicio de sesión simple y veremos cómo determinar, en código, si un usuario está autenticado y, si es así, el nombre de usuario con el que inició sesión.

Comprender el flujo de trabajo de autenticación de formularios, habilitarlo en una aplicación web y crear las páginas de inicio y cierre de sesión son todos los pasos fundamentales para crear una aplicación de ASP.NET que admita cuentas de usuario y autentique a los usuarios a través de una página web. Debido a esto y a que estos tutoriales se basan entre sí, le animaría a trabajar a seguir este tutorial en su totalidad antes de pasar al siguiente, incluso si ya ha tenido experiencia en la configuración de la autenticación de formularios en proyectos anteriores.

Descripción del flujo de trabajo de autenticación de formularios

Cuando el entorno de ejecución de ASP.NET procesa una solicitud de un recurso de ASP.NET, como una página o servicio web de ASP.NET, la solicitud genera una serie de eventos durante su ciclo de vida. Hay eventos que se generan al principio y al final de la solicitud, los que se generan cuando la solicitud se autentica y autoriza, un evento generado en el caso de una excepción no controlada, etc. Para ver una lista completa de los eventos, consulte los eventos del objeto HttpApplication.

Los módulos HTTP son clases administradas cuyo código se ejecuta en respuesta a un evento determinado en el ciclo de vida de la solicitud. ASP.NET incluye una serie de módulos HTTP que realizan tareas esenciales en segundo plano. Dos módulos HTTP integrados que son especialmente relevantes para nuestra discusión son:

  • FormsAuthenticationModule: autentica al usuario inspeccionando el vale de autenticación de formularios, que normalmente se incluye en la recopilación de cookies del usuario. Si no hay ningún vale de autenticación de formularios presente, el usuario es anónimo.
  • UrlAuthorizationModule: determina si el usuario actual está autorizado para acceder a la dirección URL solicitada. Este módulo determina la autoridad consultando las reglas de autorización especificadas en los archivos de configuración de la aplicación. ASP.NET también incluye el FileAuthorizationModule que determina la autoridad consultando las ACL de archivos solicitadas.

FormsAuthenticationModule intenta autenticar al usuario antes de la ejecución de UrlAuthorizationModule (y de FileAuthorizationModule). Si el usuario que realiza la solicitud no está autorizado para acceder al recurso solicitado, el módulo de autorización finaliza la solicitud y devuelve un estado HTTP 401 No autorizado. En escenarios de autenticación de Windows, el estado HTTP 401 se devuelve al explorador. Este código de estado hace que el explorador solicite al usuario sus credenciales a través de un cuadro de diálogo modal. Sin embargo, con la autenticación de formularios, el estado HTTP 401 No autorizado nunca se envía al explorador porque FormsAuthenticationModule detecta este estado y lo modifica para redirigir al usuario a la página de inicio de sesión (a través de un estado HTTP 302 Redirección).

La responsabilidad de la página de inicio de sesión es determinar si las credenciales del usuario son válidas y, si es así, crear un vale de autenticación de formularios y redirigir al usuario a la página que intentaba visitar. El vale de autenticación se incluye en las solicitudes posteriores a las páginas del sitio web, que usa FormsAuthenticationModule para identificar al usuario.

The Forms Authentication Workflow

Figura 1: Flujo de trabajo de autenticación de formularios

Recordar el vale de autenticación en las visitas a la página

Después de iniciar sesión, el vale de autenticación de formularios debe devolverse al servidor web en cada solicitud para que el usuario permanezca conectado mientras navega por el sitio. Normalmente, esto se logra colocando el vale de autenticación en la recopilación de cookies del usuario. Las cookies son archivos de texto pequeños que residen en el equipo del usuario y que se transmiten en los encabezados HTTP en cada solicitud al sitio web que creó la cookie. Por lo tanto, una vez creado y almacenado el vale de autenticación de formularios en las cookies del navegador, cada visita posterior a ese sitio envía el vale de autenticación junto con la solicitud, identificando así al usuario.

Un aspecto de las cookies es su expiración, que es la fecha y hora en que el navegador descarta la cookie. Cuando expira la cookie de autenticación de formularios, el usuario ya no se puede autenticar y, por tanto, se convierte en anónimo. Cuando un usuario visita desde un terminal público, es probable que desee que su vale de autenticación expire cuando cierre su explorador. Sin embargo, al visitar desde casa, es posible que ese mismo usuario quiera que se recuerde el vale de autenticación en los reinicios del explorador para que no tenga que volver a iniciar sesión cada vez que visite el sitio. A menudo, el usuario toma esta decisión en forma de casilla "Recordarme" en la página de inicio de sesión. En el paso 3 examinaremos cómo implementar una casilla "Recordarme" en la página de inicio de sesión. En el tutorial siguiente se aborda la configuración del tiempo de espera del vale de autenticación en detalle.

Nota:

Es posible que el agente de usuario utilizado para iniciar sesión en el sitio web no admita cookies. En tal caso, ASP.NET puede usar vales de autenticación de formularios sin cookies. En este modo, el vale de autenticación se codifica en la dirección URL. Veremos cuándo se usan los vales de autenticación sin cookies y cómo se crean y administran en el siguiente tutorial.

El ámbito de autenticación de formularios

FormsAuthenticationModule es código administrado que forma parte del entorno de ejecución de ASP.NET. Antes de la versión 7 del servidor web de Internet Information Services (IIS) de Microsoft, había una barrera distinta entre la canalización HTTP de IIS y la canalización del entorno de ejecución de ASP.NET. En resumen, en IIS 6 y versiones anteriores, FormsAuthenticationModule solo se ejecuta cuando se delega una solicitud de IIS al entorno de ejecución de ASP.NET. De forma predeterminada, IIS procesa contenido estático, como páginas HTML y archivos CSS y de imagen, y solo entrega las solicitudes al entorno de ejecución de ASP.NET cuando se solicita una página con una extensión de .aspx, .asmx o .ashx.

Sin embargo, IIS 7 permite canalizaciones integradas de IIS y ASP.NET. Con algunas opciones de configuración, puede configurar IIS 7 para invocar FormsAuthenticationModule para todas las solicitudes. Además, con IIS 7 puede definir reglas de autorización de direcciones URL para archivos de cualquier tipo. Para obtener más información, consulte Cambios entre la seguridad de IIS6 e IIS7, Seguridad de la plataforma web y Descripción de la autorización de direcciones URL de IIS7.

En resumen, en versiones anteriores a IIS 7, solo puede usar la autenticación de formularios para proteger los recursos administrados por el tiempo de ejecución de ASP.NET. Del mismo modo, las reglas de autorización de direcciones URL solo se aplican a los recursos administrados por el entorno de ejecución de ASP.NET. Pero con IIS 7 es posible integrar FormsAuthenticationModule y UrlAuthorizationModule en la canalización HTTP de IIS, lo que amplía esta funcionalidad a todas las solicitudes.

Paso 1: Crear un sitio web de ASP.NET para esta serie de tutoriales

Para llegar a un público lo más amplio posible, el sitio web de ASP.NET que crearemos en esta serie se creará con la versión gratuita de Microsoft de Visual Studio 2008: Visual Web Developer 2008. Implementaremos el almacén de usuarios SqlMembershipProvider en una base de datos de Microsoft SQL Server 2005 Express Edition. Si usa Visual Studio 2005 o una edición diferente de Visual Studio 2008 o SQL Server, no se preocupe: los pasos serán casi idénticos y se señalarán las diferencias importantes.

Nota:

La aplicación web de demo que se usa en cada tutorial está disponible como descarga. Esta aplicación descargable se creó con Visual Web Developer 2008 destinado a la versión 3.5 de .NET Framework. Dado que la aplicación está destinada a .NET 3.5, su archivo Web.config incluye elementos de configuración adicionales específicos de 3.5. En resumen, si aún no ha instalado .NET 3.5 en su equipo, la aplicación web descargable no funcionará sin eliminar primero el marcado específico de 3.5 de Web.config.

Para poder configurar la autenticación de formularios, primero necesitamos un sitio web ASP.NET. Empiece por crear un nuevo sitio web de ASP.NET basado en el sistema de archivos. Para ello, inicie Visual Web Developer y, a continuación, vaya al menú Archivo y elija Nuevo sitio web, mostrando el cuadro de diálogo Nuevo sitio web. Elija la plantilla sitio web de ASP.NET, establezca la lista desplegable Ubicación en Sistema de archivos, elija una carpeta para colocar el sitio web y establezca el idioma en C#. Esto creará un sitio web con una página de Default.aspx ASP.NET, una carpeta App_Data y un archivo Web.config.

Nota:

Visual Studio admite dos modos de administración de proyectos: proyectos de sitio web y proyectos de aplicaciones web. Los proyectos de sitio web carecen de un archivo de proyecto, mientras que los proyectos de aplicación web imitan la arquitectura del proyecto en Visual Studio .NET 2002/2003: incluyen un archivo de proyecto y compilan el código fuente del proyecto en un único ensamblado, que se coloca en la carpeta /bin. Visual Studio 2005 solo admitía inicialmente proyectos de sitio web, aunque el modelo de proyecto de aplicación web se volvió a introducir con Service Pack 1; Visual Studio 2008 ofrece ambos modelos de proyecto. Sin embargo, las ediciones Visual Web Developer 2005 y 2008 solo admiten proyectos de sitio web. Usaré el modelo de proyecto de sitio web. Si usa una edición que no es Express y quiere usar el modelo de proyecto de aplicación web en su lugar, no dude en hacerlo, pero tenga en cuenta que puede haber algunas discrepancias entre lo que ve en la pantalla y los pasos que debe realizar frente a las capturas de pantalla que se muestran y las instrucciones proporcionadas en estos tutoriales.

Create a New File System-Based Web Site

Figura 2: Crear un nuevo sitio web basado en el sistema de archivos (haga clic para ver la imagen a tamaño completo)

Agregar una página maestra

A continuación, agregue una nueva página maestra al sitio en el directorio raíz denominado Site.master. Las páginas maestras permiten a un desarrollador de páginas definir una plantilla para todo el sitio que se puede aplicar a páginas ASP.NET. La principal ventaja de las páginas maestras es que la apariencia general del sitio se puede definir en una sola ubicación, lo que facilita la actualización o ajuste del diseño del sitio.

Add a Master Page Named Site.master to the Website

Figura 3: Agregar una página maestra denominada Site.master al sitio web (haga clic para ver la imagen a tamaño completo)

Defina el diseño de página para todo el sitio aquí en la página maestra. Puede usar la vista Diseño y agregar cualquier diseño o controles web que necesite, o bien puede agregar manualmente el marcado manualmente en la vista Origen. He estructurado el diseño de mi página maestra para imitar el diseño usado en mi serie de tutoriales Trabajar con datos en ASP.NET 2.0 (consulte la figura 4). La página maestra usa hojas de estilos en cascada para el posicionamiento y los estilos con la configuración CSS definida en el archivo Style.css (que se incluye en la descarga asociada de este tutorial). Aunque no se puede indicar desde el marcado que se muestra a continuación, las reglas CSS se definen de modo que el contenido del <div> de navegación esté absolutamente posicionado para que aparezca a la izquierda y tenga un ancho fijo de 200 píxeles.

<%@ Master Language="C#" AutoEventWireup="true" CodeFile="Site.master.cs" Inherits="Site" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head id="Head1" runat="server">
    <title>Forms Authentication, Authorization, and User Accounts</title>
    <link href="Styles.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <div id="wrapper">
        <form id="form1" runat="server">
        
            <div id="header">
                <span class="title">User Account Tutorials</span>
            </div>
        
            <div id="content">
                <asp:contentplaceholder id="MainContent" runat="server">
                  <!-- Page-specific content will go here... -->
                </asp:contentplaceholder>
            </div>
            
            <div id="navigation">
                TODO: Menu will go here...
            </div>
        </form>
    </div>
</body>
</html>

Una página maestra define tanto el diseño de página estático como las regiones que pueden editar las páginas ASP.NET que usan la página maestra. Estas regiones editables de contenido se indican mediante el control ContentPlaceHolder, que se puede ver dentro del <div> de contenido. Nuestra página maestra tiene un solo ContentPlaceHolder (MainContent), pero las páginas maestras pueden tener varios ContentPlaceHolders.

Con el marcado especificado anteriormente, al cambiar a la vista Diseño se muestra el diseño de la página maestra. Cualquier página ASP.NET que use esta página maestra tendrá este diseño uniforme, con la capacidad de especificar el marcado de la región MainContent.

The Master Page, When Viewed Through the Design View

Figura 4: La página maestra cuando se ve a través de la vista Diseño (haga clic para ver la imagen a tamaño completo)

Creación de páginas de contenido

En este punto tenemos una página Default.aspx en nuestro sitio web, pero no usa la página maestra que acabamos de crear. Aunque es posible manipular el marcado declarativo de una página web para usar una página maestra, si la página aún no contiene contenido, es más fácil eliminar la página y volver a agregarla al proyecto, especificando la página maestra que se va a usar. Por lo tanto, empiece eliminando Default.aspx del proyecto.

A continuación, haga clic con el botón derecho en el nombre del proyecto en el Explorador de soluciones y opte por agregar un nuevo formulario web denominado Default.aspx. Esta vez, active la casilla "Seleccionar página maestra" y elija la página maestra Site.master de la lista.

Add a New Default.aspx Page Choosing to Select a Master Page

Figura 5: Agregar una nueva página Default.aspx seleccionando una página maestra (haga clic para ver la imagen a tamaño completo)

Use the Site.master Master Page

Figura 6: Usar la página maestra Site.master

Nota:

Si usa el modelo de proyecto de aplicación web, el cuadro de diálogo Agregar nuevo elemento no incluye la casilla "Seleccionar página maestra". En su lugar, debe agregar un elemento de tipo "Formulario de contenido web". Después de elegir la opción "Formulario de contenido web" y de hacer clic en Agregar, Visual Studio mostrará el mismo cuadro de diálogo Seleccionar un patrón que se muestra en la figura 6.

El nuevo marcado declarativo de la página Default.aspx incluye solo una directiva @Page que especifica la ruta de acceso al archivo de página maestra y un MainContent ContentPlaceHolder de la página maestra.

<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" Title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" Runat="Server">
</asp:Content>

Por ahora, deje Default.aspx vacío. Volveremos a él más adelante en este tutorial para agregar contenido.

Nota:

Nuestra página maestra incluye una sección para un menú o alguna otra interfaz de navegación. Crearemos una interfaz de este tipo en un tutorial futuro.

Paso 2: Habilitación de la autenticación de formularios

Con el sitio web de ASP.NET creado, nuestra siguiente tarea es habilitar la autenticación de formularios. La configuración de autenticación de la aplicación se especifica a través del elemento <authentication> de Web.config. El elemento <authentication> contiene un solo atributo denominado mode que especifica el modelo de autenticación utilizado por la aplicación. Este atributo puede tener uno de los cuatro valores siguientes:

  • Windows: como se describe en el tutorial anterior, cuando una aplicación usa la autenticación de Windows, es responsabilidad del servidor web autenticar al visitante, y esto suele hacerse a través de la autenticación básica, implícita o integrada de Windows.
  • Formularios: los usuarios se autentican a través de un formulario en una página web.
  • Passport: los usuarios se autentican mediante la red de Microsoft Passport.
  • Ninguno: no se usa ningún modelo de autenticación; todos los visitantes son anónimos.

De forma predeterminada, las aplicaciones ASP.NET usan la autenticación de Windows. Para cambiar el tipo de autenticación a la autenticación de formularios, es necesario modificar el atributo mode del elemento <authentication> a Forms.

Si el proyecto aún no contiene ningún archivo Web.config, agregue uno ahora haciendo clic con el botón derecho en el nombre del proyecto en el Explorador de soluciones, seleccionando Agregar nuevo elemento y, a continuación, agregando un archivo de configuración web.

If Your Project Does Not Yet Include Web.config, Add It Now

Figura 7: Si el proyecto aún no incluye Web.config, agréguelo ahora (haga clic para ver la imagen a tamaño completo).

A continuación, busque el elemento <authentication> y actualícelo para usar la autenticación de formularios. Después de este cambio, el marcado del archivo Web.config debe ser similar al siguiente:

<configuration>
    <system.web>
        ... Unrelated configuration settings and comments removed for brevity ...
        <!--
            The <authentication> section enables configuration 
            of the security authentication mode used by 
            ASP.NET to identify an incoming user. 
        -->
        <authentication mode="Forms" />
    </system.web>
</configuration>

Nota:

Dado que Web.config es un archivo XML, es importante el uso de mayúsculas y minúsculas. Asegúrese de establecer el atributo mode en Forms, con un mayúscula "F". Si no usa las mayúsculas y minúsculas adecuadas, como "forms", recibirá un error de configuración al visitar el sitio a través de un explorador.

El elemento <authentication> puede incluir opcionalmente un elemento secundario <forms> que contenga la configuración específica de la autenticación de formularios. Por ahora, vamos a usar la configuración de autenticación de formularios predeterminada. Exploraremos el elemento secundario <forms> con más detalle en el siguiente tutorial.

Paso 3: Crear la página de inicio de sesión

Para admitir la autenticación de formularios, nuestro sitio web necesita una página de inicio de sesión. Como se describe en la sección "Descripción del flujo de trabajo de autenticación de formularios", FormsAuthenticationModule redirigirá automáticamente al usuario a la página de inicio de sesión si intenta acceder a una página que no está autorizado para ver. También hay controles web de ASP.NET que mostrarán un vínculo a la página de inicio de sesión a usuarios anónimos. Esto plantea la pregunta "¿Cuál es la dirección URL de la página de inicio de sesión?".

De forma predeterminada, el sistema de autenticación de formularios espera que la página de inicio de sesión se llame Login.aspx y se coloque en el directorio raíz de la aplicación web. Si desea usar otra dirección URL de página de inicio de sesión, puede hacerlo especificándolo en Web.config. Veremos cómo hacerlo en el tutorial posterior.

La página de inicio de sesión tiene tres responsabilidades:

  1. Proporcionar una interfaz que permita al visitante escribir sus credenciales.
  2. Determinar si las credenciales enviadas son válidas.
  3. Iniciar la sesión del usuario creando el vale de autenticación de formularios.

Creación de la interfaz de usuario de la página de inicio de sesión

Comencemos con la primera tarea. Agregue una nueva página de ASP.NET al directorio raíz del sitio denominado Login.aspx y asóciela a la página maestra Site.master.

Add a New ASP.NET Page Named Login.aspx

Figura 8: Agregar una nueva página de ASP.NET denominada Login.aspx (haga clic para ver la imagen a tamaño completo)

La interfaz típica de la página de inicio de sesión consta de dos cuadros de texto (uno para el nombre del usuario u otro para su contraseña) y un botón para enviar el formulario. Los sitios web suelen incluir una casilla "Recordarme" que, si está activada, conserva el vale de autenticación resultante en los reinicios del explorador.

Agregue dos TextBoxes a Login.aspx y establezca sus propiedades ID en UserName y Password, respectivamente. Establezca también la propiedad TextMode de la contraseña en Contraseña. A continuación, agregue un control CheckBox y establezca su propiedad ID en RememberMe y su propiedad Text en "Recordarme". Después, agregue un botón denominado LoginButton cuya propiedad Text esté establecida en "Login". Y, por último, agregue un control Web Label y establezca su propiedad ID en InvalidCredentialsMessage, su propiedad Text en "Su nombre de usuario o contraseña no es válido. Inténtelo de nuevo.", su propiedad ForeColor en Red y su propiedad Visible en False.

En este punto, la pantalla debe ser similar a la captura de pantalla de la figura 9 y la sintaxis declarativa de la página debe ser similar a la siguiente:

<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Login.aspx.cs" Inherits="Login" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" Runat="Server">
    <h1>
        Login</h1>
    <p>
        Username:
        <asp:TextBox ID="UserName" runat="server"></asp:TextBox></p>
    <p>
        Password:
        <asp:TextBox ID="Password" runat="server" TextMode="Password"></asp:TextBox></p>
    <p>
        <asp:CheckBox ID="RememberMe" runat="server" Text="Remember Me" /> </p>
    <p>
        <asp:Button ID="LoginButton" runat="server" Text="Login" OnClick="LoginButton_Click" /> </p>
    <p>
        <asp:Label ID="InvalidCredentialsMessage" runat="server" ForeColor="Red" Text="Your username or password is invalid. Please try again."
            Visible="False"></asp:Label> </p>
</asp:Content>

The Login Page Contains Two TextBoxes, a CheckBox, a Button, and a Label

Figura 9: La página de inicio de sesión contiene dos TextBoxes, una CheckBox, un Button y una Label (haga clic para ver la imagen a tamaño completo)

Por último, cree un controlador de eventos para el evento Click de LoginButton. En el Diseñador, haga doble clic en el control Button para crear este controlador de eventos.

Determinar si las credenciales proporcionadas son válidas

Ahora es necesario implementar la tarea 2 en el controlador de eventos Click de Button, lo que determina si las credenciales proporcionadas son válidas. Para ello, debe haber un almacén de usuarios que contenga todas las credenciales de los usuarios para poder determinar si las credenciales proporcionadas coinciden con las credenciales conocidas.

Antes de ASP.NET 2.0, los desarrolladores eran responsables de implementar sus propios almacenes de usuario y escribir el código para validar las credenciales proporcionadas en el almacén. La mayoría de los desarrolladores implementarían el almacén de usuarios en una base de datos, creando una tabla denominada Usuarios con columnas como UserName, Password, Email, LastLoginDate, etc. Esta tabla, a continuación, tendría un registro por cuenta de usuario. La comprobación de las credenciales proporcionadas por un usuario implicaría consultar la base de datos para un nombre de usuario coincidente y, a continuación, asegurarse de que la contraseña de la base de datos se corresponde con la contraseña proporcionada.

Con ASP.NET 2.0, los desarrolladores deben usar uno de los proveedores de pertenencia para administrar el almacén de usuarios. En esta serie de tutoriales usaremos SqlMembershipProvider, que usa una base de datos de SQL Server para el almacén de usuarios. Al usar SqlMembershipProvider, es necesario implementar un esquema de base de datos específico que incluya las tablas, vistas y procedimientos almacenados esperados por el proveedor. Examinaremos cómo implementar este esquema en el tutorial Creación del esquema de pertenencia en SQL Server. Con el proveedor de pertenencia implementado, validar las credenciales del usuario es tan sencillo como llamar al método ValidateUser(username, password) de la clase Membership, que devuelve un valor booleano que indica la validez de la combinación de nombre de usuario y contraseña. Al ver que aún no hemos implementado el almacén de usuarios SqlMembershipProvider, no podemos usar el método ValidateUser de la clase Membership en este momento.

En lugar de tomarnos el tiempo para crear nuestra propia tabla de base de datos Usuarios personalizada (que quedaría obsoleta una vez implementada SqlMembershipProvider), vamos a codificar de forma rígida las credenciales válidas dentro de la propia página de inicio de sesión. En el controlador de eventos Click de LoginButton, agregue el código siguiente:

protected void LoginButton_Click(object sender, EventArgs e)
{
    // Three valid username/password pairs: Scott/password, Jisun/password, and Sam/password.
    string[] users = { "Scott", "Jisun", "Sam" };
    string[] passwords = { "password", "password", "password" };
    for (int i = 0; i < users.Length; i++)
    {
        bool validUsername = (string.Compare(UserName.Text, users[i], true) == 0);
        bool validPassword = (string.Compare(Password.Text, passwords[i], false) == 0);
        if (validUsername && validPassword)
        {
            // TODO: Log in the user...
            // TODO: Redirect them to the appropriate page
        }
    }
    // If we reach here, the user's credentials were invalid
    InvalidCredentialsMessage.Visible = true;
}

Como puede ver, hay tres cuentas de usuario válidas (Scott, Jisun y Sam) y las tres tienen la misma contraseña ("password"). El código recorre en bucle las matrices de usuarios y contraseñas que buscan una coincidencia válida de nombre de usuario y contraseña. Si el nombre de usuario y la contraseña son válidos, es necesario iniciar sesión del usuario y, a continuación, redirigirlos a la página adecuada. Si las credenciales no son válidas, se muestra la etiqueta InvalidCredentialsMessage.

Cuando un usuario escribe credenciales válidas, mencioné que se le redirigirá a la "página adecuada". Sin embargo, ¿cuál es la página adecuada? Recuerde que cuando un usuario visita una página que no está autorizado para ver, FormsAuthenticationModule le redirige automáticamente a la página de inicio de sesión. Al hacerlo, incluye la dirección URL solicitada en la cadena de consulta a través del parámetro ReturnUrl. Es decir, si un usuario intentó visitar ProtectedPage.aspx y no estaba autorizado para hacerlo, FormsAuthenticationModule le redirigiría a:

Login.aspx?ReturnUrl=ProtectedPage.aspx

Después de iniciar sesión correctamente, el usuario debe redirigirse de nuevo a ProtectedPage.aspx. Como alternativa, los usuarios pueden visitar la página de inicio de sesión por voluntad propia. En ese caso, después de iniciar sesión en el usuario, deben enviarse a la página de Default.aspx de la carpeta raíz.

Iniciar sesión en el usuario

Suponiendo que las credenciales proporcionadas son válidas, es necesario crear un vale de autenticación de formularios, con lo que se inicia sesión en el usuario en el sitio. La clase FormsAuthentication del espacio de nombres System.Web.Security proporciona métodos ordenados para iniciar y cerrar sesión de usuarios a través del sistema de autenticación de formularios. Aunque hay varios métodos en la clase FormsAuthentication, los tres que nos interesan en este momento son:

  • GetAuthCookie(username, persistCookie): crea un vale de autenticación de formularios para el nombre de usuario proporcionado A continuación, este método crea y devuelve un objeto HttpCookie que contiene el contenido del vale de autenticación. Si persistCookie es true, se crea una cookie persistente.
  • SetAuthCookie(username, persistCookie): llama al método GetAuthCookie(username, persistCookie) para generar la cookie de autenticación de formularios. A continuación, este método agrega la cookie devuelta por GetAuthCookie a la colección Cookies (suponiendo que se use la autenticación de formularios basados en cookies; de lo contrario, este método llama a una clase interna que controla la lógica del vale sin cookies).
  • RedirectFromLoginPage(username, persistCookie): este método llama a SetAuthCookie(username, persistCookie) y, a continuación, redirige al usuario a la página adecuada.

GetAuthCookie es útil cuando necesita modificar el vale de autenticación antes de escribir la cookie en la colección Cookies. SetAuthCookie es útil si desea crear el vale de autenticación de formularios y agregarlo a la colección Cookies, pero no desea redirigir al usuario a la página adecuada. Quizás quiera mantenerlo en la página de inicio de sesión o enviarlo a alguna página alternativa.

Puesto que queremos iniciar sesión en el usuario y redirigirle a la página adecuada, vamos a usar RedirectFromLoginPage. Actualice el controlador de eventos Click de LoginButton, reemplazando las dos líneas TODO comentadas por la siguiente línea de código:

FormsAuthentication.RedirectFromLoginPage(UserName.Text, RememberMe.Checked);

Al crear el vale de autenticación de formularios, usamos la propiedad TextBox de UserName para el parámetro username del vale de autenticación de formularios y el estado comprobado del CheckBox RememberMe para el parámetro persistCookie.

Para probar la página de inicio de sesión, visítela en un explorador. Para empezar, escriba credenciales no válidas, como el nombre de usuario "Nope" y la contraseña "wrong". Al hacer clic en el botón Iniciar sesión, se producirá una devolución de entrada y se mostrará la etiqueta InvalidCredentialsMessage.

The InvalidCredentialsMessage Label is Displayed When Entering Invalid Credentials

Figura 10: La etiqueta InvalidCredentialsMessage se muestra al escribir credenciales no válidas (haga clic para ver la imagen a tamaño completo).

A continuación, escriba credenciales válidas y haga clic en el botón Iniciar sesión. Esta vez, cuando se produce el postback, se crea un vale de autenticación de formularios y se le redirige automáticamente de vuelta a Default.aspx. En este punto ha iniciado sesión en el sitio web, aunque no hay señales visuales que indiquen que tiene la sesión iniciada. En el paso 4 veremos cómo determinar mediante programación si un usuario ha iniciado sesión o no, así como cómo identificar al usuario que visita la página.

En el paso 5 se examinan las técnicas para registrar a un usuario fuera del sitio web.

Protección de la página de inicio de sesión

Cuando el usuario escribe sus credenciales y envía el formulario de página de inicio de sesión, las credenciales (incluida su contraseña) se transmiten a través de Internet al servidor web en texto sin formato. Esto significa que cualquier hacker que examine el tráfico de red puede ver el nombre de usuario y la contraseña. Para evitarlo, es esencial cifrar el tráfico de red mediante capas de sockets seguros (SSL). Esto garantizará que las credenciales (así como el marcado HTML de toda la página) se cifren desde el momento en que abandonan el explorador hasta que el servidor web los reciba.

A menos que su sitio web contenga información confidencial, solo tendrá que usar SSL en la página de inicio de sesión y en otras páginas donde la contraseña del usuario se enviaría a través de la conexión en texto sin formato. No es necesario preocuparse por proteger el vale de autenticación de formularios, ya que, de forma predeterminada, está cifrado y firmado digitalmente (para evitar alteraciones). En el tutorial siguiente se presenta una explicación más exhaustiva sobre la seguridad de vales de autenticación de formularios.

Nota:

Muchos sitios web financieros y médicos están configurados para usar SSL en todas las páginas accesibles para los usuarios autenticados. Si va a crear un sitio web de este tipo, puede configurar el sistema de autenticación de formularios para que el vale de autenticación de formularios solo se transmita a través de una conexión segura.

Paso 4: Detección de visitantes autenticados y determinación de su identidad

En este momento, hemos habilitado la autenticación de formularios y hemos creado una página de inicio de sesión rudimentaria, pero todavía tenemos que examinar cómo podemos determinar si un usuario está autenticado o es anónimo. En determinados escenarios, es posible que deseemos mostrar datos o información diferentes en función de si un usuario autenticado o anónimo está visitando la página. Además, a menudo es necesario conocer la identidad del usuario autenticado.

Vamos a aumentar la página de Default.aspx existente para ilustrar estas técnicas. En Default.aspx, agregue dos controles Panel, uno denominado AuthenticatedMessagePanel y el otro, AnonymousMessagePanel. Agregue un control Label denominado WelcomeBackMessage en el primer Panel. En el segundo Panel, agregue un control HyperLink, establezca su propiedad Text en "Iniciar sesión" y su propiedad NavigateUrl en "~/Login.aspx". En este momento, el marcado declarativo de Default.aspx debe tener un aspecto similar al siguiente:

<%@ Page Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" Title="Untitled Page" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" Runat="Server">
    <asp:Panel runat="server" ID="AuthenticatedMessagePanel">
        <asp:Label runat="server" ID="WelcomeBackMessage"></asp:Label>
    </asp:Panel>
    
    <asp:Panel runat="Server" ID="AnonymousMessagePanel">
        <asp:HyperLink runat="server" ID="lnkLogin" Text="Log In" NavigateUrl="~/Login.aspx"></asp:HyperLink>
    </asp:Panel>
</asp:Content>

Como probablemente ya habrá adivinado, la idea aquí es mostrar solo el AuthenticatedMessagePanel a los visitantes autenticados y solo el AnonymousMessagePanel a los visitantes anónimos. Para ello, es necesario establecer las propiedades Visible de estos paneles en función de si el usuario ha iniciado sesión o no.

La propiedad Request.IsAuthenticated devuelve un valor booleano que indica si la solicitud se ha autenticado. Escriba el código siguiente en el código del controlador de eventos Page_Load:

protected void Page_Load(object sender, EventArgs e)
{
    if (Request.IsAuthenticated)
    {
        WelcomeBackMessage.Text = "Welcome back!";
    
        AuthenticatedMessagePanel.Visible = true;
        AnonymousMessagePanel.Visible = false;
    }
    else
    {
        AuthenticatedMessagePanel.Visible = false;
        AnonymousMessagePanel.Visible = true;
    }
}

Con este código aplicado, visite Default.aspx a través de un explorador. Suponiendo que todavía tiene que iniciar sesión, verá un vínculo a la página de inicio de sesión (consulte la figura 11). Haga clic en este vínculo e inicie sesión en el sitio. Como vimos en el paso 3, después de escribir sus credenciales, se le devolverá a Default.aspx, pero esta vez la página muestra el mensaje "Welcome back!" (vea la figura 12).

When Visiting Anonymously, a Log In Link is Displayed

Figura 11: Al visitar de forma anónima, se muestra un vínculo de inicio de sesión

Authenticated Users are Shown the

Figura 12: Los usuarios autenticados reciben el mensaje "Welcome back!" Mensaje

Podemos determinar la identidad del usuario que tiene la sesión iniciada mediante la propiedad User del objeto HttpContext. El objeto HttpContext representa información sobre la solicitud actual y es el hogar de objetos comunes ASP.NET como Response, Request y Session, entre otros. La propiedad User representa el contexto de seguridad de la solicitud HTTP actual e implementa la interfaz IPrincipal.

La propiedad User se establece mediante FormsAuthenticationModule. En concreto, cuando FormsAuthenticationModule encuentra un vale de autenticación de formularios en la solicitud entrante, crea un nuevo objeto GenericPrincipal y lo asigna a la propiedad User.

Los objetos de entidad de seguridad (como GenericPrincipal) proporcionan información sobre la identidad del usuario y los roles a los que pertenecen. La interfaz IPrincipal define dos miembros:

Podemos determinar el nombre del visitante actual mediante el código siguiente:

string currentUsersName = User.Identity.Name;

Al usar la autenticación de formularios, se crea un objeto FormsIdentity para la propiedad Identity de GenericPrincipal. La clase FormsIdentity siempre devuelve la cadena "Forms" para su propiedad AuthenticationType y true para su propiedad IsAuthenticated. La propiedad Name devuelve el nombre de usuario especificado al crear el vale de autenticación de formularios. Además de estas tres propiedades, FormsIdentity incluye acceso al vale de autenticación subyacente a través de su propiedad Ticket. La propiedad Ticket devuelve un objeto de tipo FormsAuthenticationTicket, que tiene propiedades como Expiration, IsPersistent, IssueDate, Name, etc.

Lo importante aquí es que el parámetro username especificado en los métodos FormsAuthentication.GetAuthCookie(username, persistCookie), FormsAuthentication.SetAuthCookie(username, persistCookie) y FormsAuthentication.RedirectFromLoginPage(username, persistCookie) sea el mismo valor devuelto por User.Identity.Name. Además, el vale de autenticación creado por estos métodos está disponible mediante la conversión de User.Identity a un objeto FormsIdentity y, a continuación, el acceso a la propiedad Ticket:

FormsIdentity ident = User.Identity as FormsIdentity;
FormsAuthenticationTicket authTicket = ident.Ticket;

Vamos a proporcionar un mensaje más personalizado en Default.aspx. Actualice el controlador de eventos Page_Load para que a la propiedad Text de la etiqueta WelcomeBackMessage se le asigne la cadena "Welcome back, username!"

WelcomeBackMessage.Text = "Welcome back, " + User.Identity.Name + "!";

En la figura 13 se muestra el efecto de esta modificación (al iniciar sesión con el usuario Scott).

The Welcome Message Includes the Currently Logged In User's Name

Figura 13: El mensaje de bienvenida incluye el nombre del usuario que tiene la sesión iniciada

Uso de los controles LoginView e LoginName

Mostrar contenido diferente para usuarios autenticados y anónimos es un requisito común; por lo tanto, se muestra el nombre del usuario que tiene la sesión iniciada. Por ese motivo, ASP.NET incluye dos controles web que proporcionan la misma funcionalidad que se muestra en la figura 13, pero sin necesidad de escribir una sola línea de código.

El control LoginView es un control web basado en plantillas que facilita la visualización de datos diferentes a usuarios autenticados y anónimos. LoginView incluye dos plantillas predefinidas:

  • AnonymousTemplate: cualquier marcado agregado a esta plantilla solo se muestra a los visitantes anónimos.
  • LoggedInTemplate: el marcado de esta plantilla solo se muestra a los usuarios autenticados.

Vamos a agregar el control LoginView a la página maestra de nuestro sitio, Site.master. En lugar de agregar solo el control LoginView, vamos a agregar un nuevo control ContentPlaceHolder y, a continuación, colocaremos el control LoginView dentro de ese nuevo ContentPlaceHolder. Los motivos de esta decisión se expondrán en breve.

Nota:

Además de AnonymousTemplate y LoggedInTemplate, el control LoginView puede incluir plantillas específicas del rol. Las plantillas específicas de rol muestran el marcado solo para los usuarios que pertenecen a un rol especificado. Examinaremos las características basadas en roles del control LoginView en un tutorial futuro.

Empiece agregando un ContentPlaceHolder denominado LoginContent a la página maestra dentro del elemento <div> de navegación. Basta con que arrastre un control ContentPlaceHolder desde el cuadro de herramientas a la vista Origen, colocando el marcado resultante justo encima del texto "TODO: Menu will go here...".

<div id="navigation">
    <asp:ContentPlaceHolder ID="LoginContent" runat="server">
    </asp:ContentPlaceHolder>
   
    TODO: Menu will go here...
</div>

A continuación, agregue un control LoginView dentro de LoginContent ContentPlaceHolder. El contenido colocado en los controles ContentPlaceHolder de la página maestra se considera contenido predeterminado para ContentPlaceHolder. Es decir, las páginas ASP.NET que usan esta página maestra pueden especificar su propio contenido para cada ContentPlaceHolder o usar el contenido predeterminado de la página maestra.

LoginView y otros controles relacionados con el inicio de sesión se encuentran en la pestaña Inicio de sesión del cuadro de herramientas.

The LoginView Control in the Toolbox

Figura 14: Control LoginView en el cuadro de herramientas

A continuación, agregue dos elementos <br /> inmediatamente después del control LoginView, pero dentro del ContentPlaceHolder. En este punto, el marcado del elemento <div> de navegación debe tener un aspecto similar al siguiente:

<div id="navigation">
    <asp:ContentPlaceHolder ID="LoginContent" runat="server">
        <asp:LoginView ID="LoginView1" runat="server">
        </asp:LoginView>
        <br /><br />
    </asp:ContentPlaceHolder>
   
    TODO: Menu will go here...
</div>

Las plantillas de LoginView se pueden definir desde el Diseñador o desde el marcado declarativo. En el Diseñador de Visual Studio, expanda la etiqueta inteligente LoginView, que enumera las plantillas configuradas en una lista desplegable. Escriba el texto "Hello, stranger" en AnonymousTemplate. A continuación, agregue un control HyperLink y establezca sus propiedades Text y NavigateUrl en "Log In" y "~/Login.aspx", respectivamente.

Después de configurar AnonymousTemplate, cambie a LoggedInTemplate y escriba el texto "Welcome back, ". A continuación, arrastre un control LoginName desde el cuadro de herramientas a LoggedInTemplate, colocándolo inmediatamente después del texto "Welcome back, ". El control LoginName, como su nombre indica, muestra el nombre del usuario que tiene iniciada la sesión. Internamente, el control LoginName solo genera la propiedad User.Identity.Name.

Después de realizar estas adiciones a las plantillas de LoginView, el marcado debe ser similar al siguiente:

<div id="navigation">
    <asp:ContentPlaceHolder ID="LoginContent" runat="server">
        <asp:LoginView ID="LoginView1" runat="server">
            <LoggedInTemplate>
                Welcome back,
                <asp:LoginName ID="LoginName1" runat="server" />.
            </LoggedInTemplate>
            <AnonymousTemplate>
                Hello, stranger.
                <asp:HyperLink ID="lnkLogin" runat="server" NavigateUrl="~/Login.aspx">Log In</asp:HyperLink>
            </AnonymousTemplate>
        </asp:LoginView>
        
        <br /><br />
    </asp:ContentPlaceHolder>
   
    TODO: Menu will go here...
</div>

Con esta adición a la página maestra Site.master, cada página de nuestro sitio web mostrará un mensaje diferente en función de si el usuario está autenticado. En la figura 15 se muestra la página Default.aspx cuando el usuario Jisun la visita a través de un explorador. El mensaje "Welcome back, Jisun" se repite dos veces: una vez en la sección de navegación de la página maestra de la izquierda (a través del control LoginView que acabamos de agregar) y otra vez en el área de contenido de Default.aspx (a través de los controles Panel y de la lógica de programación).

The LoginView Control Displays

Figura 15: El control LoginView muestra "Welcome back, Jisun".

Dado que agregamos LoginView a la página maestra, puede aparecer en todas las páginas de nuestro sitio. Sin embargo, puede haber páginas web en las que no queramos mostrar este mensaje. Una de estas páginas es la página de inicio de sesión, ya que un vínculo a la página de inicio de sesión parece fuera de su lugar. Puesto que colocamos el control LoginView en un ContentPlaceHolder en la página maestra, podemos invalidar este marcado predeterminado en nuestra página de contenido. Abra Login.aspx y vaya al Diseñador. Dado que no hemos definido explícitamente un control Content en Login.aspx para LoginContent ContentPlaceHolder en la página maestra, la página de inicio de sesión mostrará el marcado predeterminado de la página maestra para este ContentPlaceHolder. Puede verlo a través del Diseñador: LoginContent ContentPlaceHolder muestra el marcado predeterminado (el control LoginView).

The Login Page Shows the Default Content for the Master Page's LoginContent ContentPlaceHolder

Figura 16: La página Inicio de sesión muestra el contenido predeterminado para el LoginContent ContentPlaceHolder de la página maestra (haga clic para ver la imagen a tamaño completo)

Para invalidar el marcado predeterminado para LoginContent ContentPlaceHolder, haga clic con el botón derecho en la región del Diseñador y elija la opción Crear contenido personalizado en el menú contextual (al usar Visual Studio 2008, ContentPlaceHolder incluye una etiqueta inteligente que, cuando se selecciona, ofrece la misma opción). Esto agrega un nuevo control Content al marcado de la página y, por tanto, nos permite definir contenido personalizado para esta página. Puede agregar un mensaje personalizado aquí, como "Inicie sesión...", pero vamos a dejar esto en blanco.

Nota:

En Visual Studio 2005, la creación de contenido personalizado crea un control Content vacío en la página ASP.NET. Sin embargo, en Visual Studio 2008, la creación de contenido personalizado copia el contenido predeterminado de la página maestra en el control Contenido recién creado. Si usa Visual Studio 2008, después de crear el control Content, asegúrese de borrar el contenido copiado de la página maestra.

En la figura 17 se muestra la página Login.aspx cuando se visita desde un explorador después de realizar este cambio. Tenga en cuenta que no hay ningún mensaje "Hello, stranger" ni "Welcome back, username" en el <div> de navegación izquierdo, como sucede al visitar Default.aspx.

The Login Page Hides the Default LoginContent ContentPlaceHolder's Markup

Figura 17: La página de inicio de sesión oculta el marcado predeterminado LoginContent ContentPlaceHolder (haga clic para ver la imagen a tamaño completo)

Paso 5: Cerrar sesión

En el paso 3 hemos visto la creación de una página de inicio de sesión para registrar a un usuario en el sitio, pero todavía tenemos que ver cómo cerrar la sesión de un usuario. Además de los métodos para iniciar la sesión de un usuario, la clase FormsAuthentication también proporciona un método SignOut. El método SignOut destruye el vale de autenticación de formularios y, por tanto, cierra la sesión del usuario del sitio.

Ofrecer un vínculo de cierre de sesión es una característica tan común que ASP.NET incluye un control diseñado específicamente para cerrar la sesión de un usuario. El control LoginStatus muestra un LinkButton "Login" o "Logout", en función del estado de autenticación del usuario. Un LinkButton "Login" se representa para los usuarios anónimos, mientras que se muestra un LinkButton "Logout" para los usuarios autenticados. El texto de los LinkButtons "Login" y "Logout" se puede configurar a través de las propiedades LoginText y LogoutText de LoginStatus.

Al hacer clic en el LinkButton "Login" se produce un postback, desde el que se emite una redirección a la página de inicio de sesión. Al hacer clic en el LinkButton "Logout", el control LoginStatus invocará el método FormsAuthentication.SignOff y, a continuación, redirigirá al usuario a una página. La página a la que se redirige el usuario que ha cerrado sesión depende de la propiedad LogoutAction, que se puede asignar a uno de los tres valores siguientes:

  • Actualizar: valor predeterminado; redirige al usuario a la página que acaba de visitar. Si la página que acaba de visitar no permite a los usuarios anónimos, FormsAuthenticationModule redirigirá automáticamente al usuario a la página de inicio de sesión.

Puede que tenga curiosidad por saber por qué se realiza aquí un redireccionamiento. Si el usuario quiere permanecer en la misma página, ¿por qué necesita el redireccionamiento explícito? El motivo es que cuando se hace clic en el LinkButton "Logoff", el usuario sigue teniendo el vale de autenticación de formularios en su colección de cookies. Por lo tanto, la solicitud de postback es una solicitud autenticada. El control LoginStatus llama al método SignOut, pero esto sucede después de que FormsAuthenticationModule haya autenticado al usuario. Por lo tanto, una redirección explícita hace que el explorador vuelva a solicitar la página. Cuando el explorador vuelve a solicitar la página, se ha quitado el vale de autenticación de formularios y, por tanto, la solicitud entrante es anónima.

  • Redireccionamiento: se redirige al usuario a la dirección URL especificada por la propiedad LogoutPageUrl de LoginStatus.
  • RedirectToLoginPage: se redirige al usuario a la página de inicio de sesión.

Vamos a agregar un control LoginStatus a la página maestra y configurarlo para usar la opción Redireccionamiento para enviar al usuario a una página que muestre un mensaje que confirme que se ha cerrado la sesión. Empiece creando una página en el directorio raíz denominada Logout.aspx. No olvide asociar esta página a la página maestra Site.master. A continuación, escriba un mensaje en el marcado de la página que explique al usuario que se ha cerrado su sesión.

A continuación, vuelva a la página maestra Site.master y agregue un control LoginStatus debajo de LoginView en LoginContent ContentPlaceHolder. Establezca la propiedad LogoutAction del control LoginStatus en Redirect y su propiedad LogoutPageUrl en "~/Logout.aspx".

<div id="navigation">
    <asp:ContentPlaceHolder ID="LoginContent" runat="server">
        <asp:LoginView ID="LoginView1" runat="server">
            <LoggedInTemplate>
                Welcome back,
                <asp:LoginName ID="LoginName1" runat="server" />.
            </LoggedInTemplate>
            <AnonymousTemplate>
                Hello, stranger.
                <asp:HyperLink ID="lnkLogin" runat="server" NavigateUrl="~/Login.aspx">Log In</asp:HyperLink>
            </AnonymousTemplate>
        </asp:LoginView>
        <br />
        <asp:LoginStatus ID="LoginStatus1" runat="server" LogoutAction="Redirect" LogoutPageUrl="~/Logout.aspx" />
        
        <br /><br />
    </asp:ContentPlaceHolder>
   
    TODO: Menu will go here...
</div>

Dado que LoginStatus está fuera del control LoginView, aparecerá tanto para los usuarios anónimos como para los autenticados, pero no pasa nada porque LoginStatus mostrará correctamente un LinkButton "Login" o "Logout". Con la adición del control LoginStatus, el HyperLink "Iniciar sesión" de AnonymousTemplate es superfluo, así que puede quitarlo.

En la figura 18 se muestra Default.aspx cuando Jisun la visita. Tenga en cuenta que la columna izquierda muestra el mensaje "Welcome back, Jisun" junto con un vínculo para cerrar sesión. Al hacer clic en el LinkButton de cierre de sesión, se produce un postback, se cierra la sesión de Jisun y se le redirige a Logout.aspx. Como se muestra en la figura 19, en el momento en que Jisun llega a Logout.aspx, ya se ha cerrado la sesión y, por tanto, es anónimo. Por lo tanto, la columna izquierda muestra el texto "Welcome, stranger" y un vínculo a la página de inicio de sesión.

Default.aspx Shows

Figura 18: Default.aspx muestra "Welcome back, Jisun" junto con un LinkButton "Logout" (haga clic para ver la imagen a tamaño completo)

Logout.aspx Shows

Figura 19: Logout.aspx muestra "Welcome, stranger" junto con un LinkButton "Login" (haga clic para ver la imagen a tamaño completo)

Nota:

Le animo a que personalice la página Logout.aspx para ocultar el elemento LoginContent ContentPlaceHolder de la página maestra (como hicimos para Login.aspx en el paso 4). El motivo es que el LinkButton "Login" representado por el control LoginStatus (el que se encuentra debajo de "Hello, stranger") envía al usuario a la página de inicio de sesión, que pasa la dirección URL actual en el parámetro querystring de ReturnUrl. En resumen, si un usuario que ha cerrado la sesión hace clic en el LinkButton "Login" de LoginStatus y luego inicia sesión, se le redirigirá de nuevo a Logout.aspx, lo que podría confundirlo fácilmente.

Resumen

En este tutorial comenzamos con un examen del flujo de trabajo de autenticación de formularios y luego pasamos a implementar la autenticación de formularios en una aplicación ASP.NET. La autenticación de formularios se basa en FormsAuthenticationModule, que tiene dos responsabilidades: identificar a los usuarios en función de su vale de autenticación de formularios y redirigir a los usuarios no autorizados a la página de inicio de sesión.

La clase FormsAuthentication de .NET Framework incluye métodos para crear, inspeccionar y quitar vales de autenticación de formularios. La propiedad Request.IsAuthenticated y el objeto User proporcionan más compatibilidad mediante programación para determinar si una solicitud está autenticada, así como información sobre la identidad del usuario. También están los controles LoginView, LoginStatus y LoginName Web, que proporcionan a los desarrolladores una forma rápida y sin código para realizar muchas tareas comunes relacionadas con el inicio de sesión. Examinaremos estos y otros controles web relacionados con el inicio de sesión con mayor detalle en tutoriales futuros.

En este tutorial se proporciona información general sobre la autenticación de formularios. No examinamos las opciones de configuración ordenadas, analizamos cómo funcionan los vales de autenticación de formularios sin cookies ni exploramos cómo ASP.NET protege el contenido del vale de autenticación de formularios.

¡Feliz programación!

Lecturas adicionales

Para obtener más información sobre los temas tratados en este tutorial, consulte los siguientes recursos:

Aprendizaje en vídeo sobre temas incluidos en este tutorial

Acerca del autor

Scott Mitchell, autor de siete libros de ASP/ASP.NET y fundador de 4GuysFromRolla.com, trabaja con tecnologías web de Microsoft desde 1998. Scott trabaja como consultor independiente, entrenador y escritor. Su último libro es Sams Teach Yourself ASP.NET 2.0 in 24 Hours. Puede ponerse en contacto con él via mitchell@4GuysFromRolla.com. o a través de su blog, que se puede encontrar en http://ScottOnWriting.NET.

Agradecimientos especiales a...

Muchos revisores han evaluado esta serie de tutoriales. El revisor principal de este tutorial es Esta serie de tutoriales fue revisada por muchos revisores colaboradores. Entre los revisores principales de este tutorial están Alicja Maziarz, John Suru y Teresa Murphy. ¿Le interesa revisar mis próximos artículos de MSDN? Si es así, escríbame a mitchell@4GuysFromRolla.com.