Crear el esquema de pertenencia en SQL Server (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 plataforma ASP.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

Este tutorial comienza examinando técnicas para agregar el esquema necesario a la base de datos con el fin de usar SqlMembershipProvider. Después, examinaremos las tablas clave en el esquema y analizaremos su propósito e importancia. Este tutorial termina con un vistazo a cómo indicar a una aplicación ASP.NET qué proveedor debe usar el marco de pertenencia.

Introducción

Los dos tutoriales anteriores examinaron el uso de la autenticación de formularios para identificar a los visitantes del sitio web. El marco de autenticación de formularios facilita a los desarrolladores iniciar sesión de un usuario en un sitio web y recordarlos en las visitas a la página mediante el uso de vales de autenticación. La clase FormsAuthentication incluye métodos para generar el vale y agregarlo a las cookies del visitante. El FormsAuthenticationModule examina todas las solicitudes entrantes y, para aquellos con un vale de autenticación válido, crea y asocia un GenericPrincipal y un objeto FormsIdentity con la solicitud actual. La autenticación de formularios es simplemente un mecanismo para conceder un vale de autenticación a un visitante al iniciar sesión y, en solicitudes posteriores, analizar ese vale para determinar la identidad del usuario. Para que una aplicación web admita cuentas de usuario, todavía es necesario implementar un almacén de usuarios y agregar funcionalidad para validar las credenciales, registrar nuevos usuarios y la gran cantidad de otras tareas relacionadas con las cuentas de usuario.

Antes de ASP.NET 2.0, los desarrolladores se encargaban de implementar todas estas tareas relacionadas con las cuentas de usuario. Afortunadamente, el equipo de ASP.NET se dio cuenta de este problema e introdujo el marco de pertenencia con ASP.NET 2.0. El marco de pertenencia es un conjunto de clases de .NET Framework que proporciona una interfaz de programación para realizar tareas principales relacionadas con las cuentas de usuario. Este marco se crea sobre el modelo de proveedor, que permite a los desarrolladores conectar una implementación personalizada a una API estandarizada.

Como se describe en el tutorial de Aspectos básicos de seguridad y soporte de ASP.NET, .NET Framework se incluye con dos proveedores de pertenencia integrados: ActiveDirectoryMembershipProvider y SqlMembershipProvider. Como su nombre implica, el SqlMembershipProvider usa una base de datos de Microsoft SQL Server como almacén de usuarios. Para poder usar este proveedor en una aplicación, es necesario indicar al proveedor qué base de datos se va a usar como almacén. Como podrás imaginar, el SqlMembershipProvider espera que la base de datos del almacén de usuarios tenga ciertas tablas de base de datos, vistas y procedimientos almacenados. Es necesario agregar este esquema esperado a la base de datos seleccionada.

En este tutorial se inicia mediante el examen de técnicas para agregar el esquema necesario a la base de datos con el fin de usar el SqlMembershipProvider. Después, examinaremos las tablas clave en el esquema y analizaremos su propósito e importancia. Este tutorial termina con un vistazo a cómo indicar a una aplicación ASP.NET qué proveedor debe usar el marco de pertenencia.

Comencemos.

Paso 1: decidir dónde colocar el almacén de usuarios

Los datos de una aplicación ASP.NET se almacenan normalmente en una serie de tablas de una base de datos. Al implementar el esquema de base de datos SqlMembershipProvider, debemos decidir si se debe colocar el esquema de pertenencia en la misma base de datos que los datos de la aplicación o en una base de datos alternativa.

Recomiendo localizar el esquema de pertenencia en la misma base de datos que los datos de la aplicación por los siguientes motivos:

  • Mantenimiento " una aplicación cuyos datos se encapsulan en una base de datos es más fácil de comprender, mantener e implementar que una aplicación que tiene dos bases de datos independientes.
  • integridad relacional ' mediante la búsqueda de las tablas relacionadas con la pertenencia en la misma base de datos que las tablas de aplicación es posible establecer restricciones de clave externa entre las claves principales de las tablas relacionadas con la pertenencia y las tablas de aplicaciones relacionadas con la pertenencia.

Desacoplar el almacén de usuarios y los datos de la aplicación en bases de datos separadas solo tiene sentido si tienes varias aplicaciones que utilizan bases de datos separadas, pero necesitan compartir un almacén de usuarios común.

Crear una base de datos

La aplicación que hemos estado compilando desde el segundo tutorial aún no ha necesitado una base de datos. Sin embargo, necesitamos una para el almacén de usuarios. Vamos a crear una y, a continuación, agregarla al esquema requerido por el proveedor SqlMembershipProvider (consulte el paso 2).

Nota:

En esta serie de tutoriales usaremos una base de datos Microsoft SQL Server 2005 Express Edition para almacenar nuestras tablas de aplicaciones y el esquema SqlMembershipProvider. Esta decisión se tomó por dos motivos: en primer lugar, debido a su costo (gratuito), Express Edition es la versión de SQL Server 2005 más accesible; en segundo lugar, las bases de datos de SQL Server 2005 Express Edition pueden colocarse directamente en la carpeta App_Data de la aplicación web, lo que facilita enormemente la tarea de empaquetar la base de datos y la aplicación web juntas en un archivo ZIP y volver a implementarla sin instrucciones especiales de instalación ni opciones de configuración. Si prefiere seguir con una versión que no sea la Express Edition de SQL Server, no dude en hacerlo. Los pasos son prácticamente idénticos. El esquema SqlMembershipProvider funcionará con cualquier versión de Microsoft SQL Server 2000 y versiones posteriores.

En el Explorador de soluciones, haga clic con el botón derecho en la carpeta App_Data y elija Agregar nuevo elemento. (Si no ve una carpeta App_Data en el proyecto, haga clic con el botón derecho en el proyecto en el Explorador de soluciones, seleccione Agregar carpeta ASP.NET y seleccione App_Data). En el cuadro de diálogo Agregar nuevo elemento, elija agregar una nueva base de datos SQL denominada SecurityTutorials.mdf. En este tutorial agregaremos el esquema SqlMembershipProvider a esta base de datos; en tutoriales posteriores crearemos tablas adicionales para capturar los datos de la aplicación.

Add a New SQL Database Named SecurityTutorials.mdf Database to the App_Data Folder

Ilustración 1: agregar una nueva base de datos SQL denominada Base de datos SecurityTutorials.mdf a la carpeta App_Data (Haga clic para ver la imagen a tamaño completo)

Agregar una base de datos a la carpeta App_Data la incluye automáticamente en la vista Explorador de bases de datos. (En la versión que no es Express Edition de Visual Studio, el Explorador de bases de datos se denomina Explorador de servidores). Vaya al Explorador de bases de datos y expanda la base de datos SecurityTutorials recién agregada. Si no ve el Explorador de bases de datos en la pantalla, vaya al menú Ver y elija Explorador de bases de datos o presione Ctrl+Alt+S. Como se muestra en la ilustración 2, la base de datos SecurityTutorials está vacía: no contiene tablas, ninguna vista ni procedimientos almacenados.

The SecurityTutorials Database is Currently Empty

Ilustración 2: la base de datos SecurityTutorials está vacía actualmente (Haga clic para ver la imagen a tamaño completo)

Paso 2: agregar el esquema SqlMembershipProvider a la base de datos

El SqlMembershipProvider requiere que se instale un conjunto determinado de tablas, vistas y procedimientos almacenados en la base de datos del almacén de usuarios. Estos objetos de base de datos necesarios se pueden agregar mediante la herramienta aspnet_regsql.exe. Este archivo se encuentra en la carpeta %WINDIR%\Microsoft.Net\Framework\v2.0.50727\.

Nota:

La herramienta aspnet_regsql.exe ofrece funcionalidad de línea de comandos y una interfaz gráfica de usuario. La interfaz gráfica es más fácil de usar y es lo que examinaremos en este tutorial. La interfaz de la línea de comandos es útil cuando es necesario automatizar la adición del esquema de SqlMembershipProvider, como en scripts de compilación o escenarios de pruebas automatizadas.

La herramienta aspnet_regsql.exe se usa para agregar o quitar servicios de aplicaciones ASP.NET a una base de datos de SQL Server especificada. Los servicios de aplicación de ASP.NET abarcan los esquemas de SqlMembershipProvider y SqlRoleProvider, junto con los esquemas de los proveedores basados en SQL para otros marcos de ASP.NET 2.0. Necesitamos proporcionar dos bits de información a la herramienta aspnet_regsql.exe:

  • Si queremos agregar o quitar servicios de aplicación, y
  • Base de datos de la que se va a agregar o quitar el esquema de servicios de aplicación

Al pedir que use la base de datos, la herramienta aspnet_regsql.exe nos pide que proporcionemos el nombre del servidor en el que reside la base de datos, las credenciales de seguridad para conectarse a la base de datos y el nombre de la base de datos. Si usa la edición que no es Express de SQL Server, ya debe conocer esta información, ya que es la misma información que debe proporcionar a través de una cadena de conexión al trabajar con la base de datos a través de una página web ASP.NET. Sin embargo, determinar el nombre del servidor y la base de datos al usar una base de datos de SQL Server 2005 Express Edition en la carpeta App_Data, es un poco más complicado.

En la siguiente sección se examina una manera sencilla de especificar el nombre del servidor y la base de datos de una base de datos de SQL Server 2005 Express Edition en la carpeta App_Data. Si no usa SQL Server 2005 Express Edition, no dude en ir directamente a la sección Instalación de los servicios de aplicaciones.

Determinar el nombre del servidor y la base de datos de una base de datos de SQL Server 2005 Express Edition en la carpeta App_Data

Para poder usar la herramienta aspnet_regsql.exe necesitamos conocer los nombres de servidor y base de datos. El nombre del servidor es localhost\InstanceName. Lo más probable es que el InstanceName sea SQLExpress. Sin embargo, si instaló SQL Server 2005 Express Edition manualmente (es decir, no lo instaló automáticamente al instalar Visual Studio), es posible que haya seleccionado un nombre de instancia diferente.

El nombre de la base de datos es un poco más complicado de determinar. Las bases de datos de la carpeta App_Data suelen tener un nombre de base de datos que incluye un identificador único global junto con la ruta de acceso al archivo de base de datos. Es necesario determinar este nombre de base de datos para agregar el esquema de servicios de aplicación a través de aspnet_regsql.exe.

La manera más fácil de determinar el nombre de la base de datos es examinarlo a través de SQL Server Management Studio. SQL Server Management Studio proporciona una interfaz gráfica para administrar bases de datos de SQL Server 2005, pero no se incluye con la versión Express Edition de SQL Server 2005. La buena noticia es que puede descargar la edición Express gratuita de SQL Server Management Studio.

Nota:

Si también tiene instalada una versión que no sea Express Edition de SQL Server 2005 en el escritorio, es probable que se instale la versión completa de Management Studio. Puede usar la versión completa para determinar el nombre de la base de datos, siguiendo los mismos pasos que se describen a continuación para Express Edition.

Empiece por cerrar Visual Studio para asegurarse de que se cierran los bloqueos impuestos por Visual Studio en el archivo de base de datos. A continuación, inicie SQL Server Management Studio y conéctese a la base de datos localhost\InstanceName para SQL Server 2005 Express Edition. Como se indicó anteriormente, es probable que el nombre de la instancia sea SQLExpress. En la opción Autenticación, seleccione Autenticación de Windows.

Connect to the SQL Server 2005 Express Edition Instance

Ilustración 3: conectarse a la instancia de SQL Server 2005 Express Edition (Haga clic para ver la imagen a tamaño completo)

Después de conectarse a la instancia de SQL Server 2005 Express Edition, Management Studio muestra carpetas para las bases de datos, la configuración de seguridad, los objetos de servidor, etc. Si expande la pestaña Bases de datos, verá que la base de datos SecurityTutorials.mdfno está registrada en la instancia de base de datos; primero es necesario adjuntar la base de datos.

Haga clic con el botón derecho en la carpeta Bases de datos y elija Adjuntar en el menú contextual. Se mostrará el cuadro de diálogo Adjuntar bases de datos. Desde aquí, haga clic en el botón Agregar, vaya a la base de datos SecurityTutorials.mdf y haga clic en Aceptar. En la ilustración 4 se muestra el cuadro de diálogo Adjuntar bases de datos después de seleccionar la base de datos SecurityTutorials.mdf. En la ilustración 5 se muestra el Explorador de objetos de Management Studio después de que la base de datos se haya adjuntado correctamente.

Attach the SecurityTutorials.mdf Database

Ilustración 4: adjuntar la base de datos SecurityTutorials.mdf (Haga clic para ver la imagen a tamaño completo)

The SecurityTutorials.mdf Database Appears in the Databases Folder

Ilustración 5: la base de datos SecurityTutorials.mdf aparece en la carpeta Bases de datos (Haga clic para ver la imagen a tamaño completo)

Como se muestra en la ilustración 5, la base de datos SecurityTutorials.mdf tiene un nombre bastante confuso. Vamos a cambiarlo a un nombre más sencillo (y más fácil de escribir). Haga clic con el botón derecho en la base de datos, elija Cambiar nombre en el menú contextual y cámbiele el nombre a SecurityTutorialsDatabase. Esto no cambia el nombre de archivo, solo el nombre que usa la base de datos para identificarse en SQL Server.

Rename the Database to SecurityTutorialsDatabase

Ilustración 6: cambiar el nombre de la base de datos a SecurityTutorialsDatabase(Haga clic para ver la imagen a tamaño completo)

En este momento conocemos los nombres de servidor y base de datos del archivo de base de datos SecurityTutorials.mdf: localhost\InstanceName y SecurityTutorialsDatabase, respectivamente. Ahora estamos listos para instalar los servicios de aplicación a través de la herramienta aspnet_regsql.exe.

Instalación de los servicios de aplicación

Para iniciar la herramienta aspnet_regsql.exe, vaya al menú Inicio y elija Ejecutar. Escriba %WINDIR%\Microsoft.Net\Framework\v2.0.50727\aspnet_regsql.exe en el cuadro de texto y haga clic en Aceptar. Como alternativa, puede usar el Explorador de Windows para explorar en profundidad la carpeta adecuada y hacer doble clic en el archivo aspnet_regsql.exe. Cualquiera de los enfoques tendrá los mismos resultados.

La ejecución de la herramienta aspnet_regsql.exe sin ningún argumento de línea de comandos inicia la interfaz gráfica de usuario del Asistente para instalación de SQL Server ASP.NET. El asistente facilita la adición o eliminación de los servicios de aplicación de ASP.NET en una base de datos especificada. La primera pantalla del asistente, que se muestra en la ilustración 7, describe el propósito de la herramienta.

Use the ASP.NET SQL Server Setup Wizard Makes to Add the Membership Schema

Ilustración 7: usar el Asistente para instalación de SQL Server ASP.NET para agregar el esquema de pertenencia (Haga clic para ver la imagen a tamaño completo)

El segundo paso del asistente nos pregunta si queremos agregar los servicios de aplicación o quitarlos. Puesto que queremos agregar las tablas, vistas y procedimientos almacenados necesarios para la SqlMembershipProvider, elija la opción Configurar SQL Server para los servicios de aplicaciones. Más adelante, si desea quitar este esquema de la base de datos, vuelva a ejecutar este asistente, pero elija la opción Quitar información de servicios de aplicación de una base de datos existente.

Choose the Configure SQL Server for Application Services Option

Ilustración 8: elija la opción Configurar SQL Server para servicios de aplicaciones (Haga clic para ver la imagen a tamaño completo)

El tercer paso solicita la información de la base de datos: el nombre del servidor, la información de autenticación y el nombre de la base de datos. Si ha seguido este tutorial y ha agregado la base de datos de SecurityTutorials.mdf a App_Data, la adjuntó a localhost\InstanceName y la cambió de nombre a SecurityTutorialsDatabase, use los siguientes valores:

  • Servidor: localhost\InstanceName
  • Autenticación de Windows
  • Base de datos: SecurityTutorialsDatabase

Enter the Database Information

Ilustración 9: escriba la información de la base de datos (Haga clic para ver la imagen a tamaño completo)

Después de escribir la información de la base de datos, haga clic en Siguiente. El paso final resume los pasos que se realizarán. Haga clic en Siguiente para instalar los servicios de aplicación y, a continuación, en Finalizar para completar el asistente.

Nota:

Si usó Management Studio para adjuntar la base de datos y cambiar el nombre del archivo de base de datos, asegúrese de desasociar la base de datos y cerrar Management Studio antes de volver a abrir Visual Studio. Para desasociar la base de datos SecurityTutorialsDatabase, haga clic con el botón derecho en el nombre de la base de datos y, en el menú Tareas, elija Separar.

Tras finalizar el asistente, vuelva a Visual Studio y vaya al Explorador de bases de datos. Expanda la carpeta Tablas . Debería ver una serie de tablas cuyos nombres comienzan por el prefijo aspnet_. Del mismo modo, puede encontrarse una variedad de vistas y procedimientos almacenados en las carpetas Vistas y Procedimientos almacenados. Estos objetos de base de datos componen el esquema de servicios de aplicación. Examinaremos los objetos de base de datos específicos de rol y pertenencia en el paso 3.

A Variety of Tables, Views, and Stored Procedures Have Been Added to the Database

Ilustración 10: se han agregado varios procedimientos almacenados, vistas y tablas a la base de datos (Haga clic para ver la imagen a tamaño completo)

Nota:

La interfaz gráfica de usuario de la herramienta aspnet_regsql.exe instala todo el esquema de servicios de aplicación. Pero al ejecutar aspnet_regsql.exe desde la línea de comandos, puede especificar qué componentes de servicios de aplicación concretos instalar (o quitar). Por lo tanto, si desea agregar solo las tablas, vistas y procedimientos almacenados necesarios para los proveedores de SqlMembershipProvider y SqlRoleProvider, ejecute aspnet_regsql.exe desde la línea de comandos. Como alternativa, puede ejecutar manualmente el subconjunto adecuado de scripts de creación de T-SQL que usa aspnet_regsql.exe. Estos scripts se encuentran en la carpeta WINDIR%\Microsoft.Net\Framework\v2.0.50727\ con nombres como InstallCommon.sql,InstallMembership.sql,InstallRoles.sql, InstallProfile.sql,InstallSqlState.sql, etc.

En este momento hemos creado los objetos de base de datos necesarios para el SqlMembershipProvider. Sin embargo, todavía necesitamos indicar al marco de pertenencia que debe usar el SqlMembershipProvider (en comparación con el ActiveDirectoryMembershipProvider) y que el SqlMembershipProvider debe usar la base de datos SecurityTutorials. Veremos cómo especificar qué proveedor usar y cómo personalizar la configuración del proveedor seleccionado en el paso 4. Pero en primer lugar, echemos un vistazo más profundo a los objetos de base de datos que se acaban de crear.

Paso 3: un vistazo a las tablas principales del esquema

Al trabajar con los marcos de pertenencia y roles en una aplicación de ASP.NET, el proveedor encapsula los detalles de implementación. En los tutoriales futuros, se interactuará con estos marcos a través de las clases Membership y Roles de .NET Framework. Al usar estas API de alto nivel no es necesario preocuparnos por los detalles de bajo nivel, como qué consultas se ejecutan o qué tablas modifican el SqlMembershipProvider y SqlRoleProvider.

Dado esto, podríamos usar con confianza los marcos de pertenencia y roles sin haber explorado el esquema de base de datos creado en el paso 2. Sin embargo, al crear las tablas para almacenar los datos de la aplicación, es posible que tengamos que crear entidades relacionadas con usuarios o roles. Ayuda a familiarizarse con los esquemas SqlMembershipProvider y SqlRoleProvider al establecer restricciones de clave externa entre las tablas de datos de la aplicación y esas tablas creadas en el paso 2. Además, en determinadas circunstancias raras es posible que necesitemos interactuar con el usuario y los almacenes de roles directamente en el nivel de base de datos (en lugar de a través de las clases Membership o Roles).

Creación de particiones del almacén de usuarios en aplicaciones

Los marcos de pertenencia y roles están diseñados para que un único usuario y almacén de roles se puedan compartir entre muchas aplicaciones diferentes. Una aplicación ASP.NET que use los marcos de pertenencia o roles debe especificar qué partición de aplicación se va a usar. En resumen, varias aplicaciones web pueden usar los mismos almacenes de roles y usuarios. En la figura 11 se muestran los almacenes de usuarios y roles que se dividen en tres aplicaciones: HRSite, CustomerSite y SalesSite. Cada una de estas tres aplicaciones web tiene sus propios usuarios y roles únicos, pero todos almacenan físicamente su cuenta de usuario e información de roles en las mismas tablas de base de datos.

User Accounts May Be Partitioned Across Multiple Applications

Ilusttación 11: las cuentas de usuario se pueden particionar entre varias aplicaciones (Haga clic para ver la imagen a tamaño completo)

La tabla aspnet_Applications es lo que define estas particiones. Cada aplicación que usa la base de datos para almacenar la información de la cuenta de usuario se representa mediante una fila de esta tabla. La tabla aspnet_Applications tiene cuatro columnas: ApplicationId, ApplicationName, LoweredApplicationName y Description. ApplicationId es de tipo uniqueidentifier y es la clave principal de la tabla; ApplicationName proporciona un nombre único descriptivo para cada aplicación.

Las demás tablas relacionadas con la pertenencia y los roles se vinculan al campo de ApplicationId en aspnet_Applications. Por ejemplo, la tabla aspnet_Users, que contiene un registro para cada cuenta de usuario, tiene un ApplicationIdcampo de clave externa; lo mismo ocurre con la tabla aspnet_Roles. El campo ApplicationId de estas tablas especifica la partición de aplicación a la que pertenece la cuenta de usuario o el rol.

Almacenar información de la cuenta de usuario

La información de la cuenta de usuario se hospeda en dos tablas: aspnet_Users y aspnet_Membership. La tabla aspnet_Users contiene campos que contienen la información esencial de la cuenta de usuario. Las tres columnas más pertinentes son:

  • UserId
  • UserName
  • ApplicationId

UserId es la clave principal (y de tipo uniqueidentifier). UserName es de tipo nvarchar(256) y, junto con la contraseña, compone las credenciales del usuario. (La contraseña de un usuario se almacena en la tabla aspnet_Membership ). ApplicationId vincula la cuenta de usuario a una aplicación determinada en aspnet_Applications. Hay una restricción compuesta UNIQUE en las UserName columnas y ApplicationId. Esto garantiza que en una aplicación determinada cada UserName sea único, pero permite usar la misma UserName en diferentes aplicaciones.

La tabla aspnet_Membership incluye información adicional de la cuenta de usuario, como la contraseña del usuario, la dirección de correo electrónico, la última fecha y hora de inicio de sesión, etc. Hay una correspondencia uno a uno entre los registros de las tablas aspnet_Users y aspnet_Membership. El campo UserId de aspnet_Membership garantiza esta relación, que actúa como clave principal de la tabla. Al igual que la tabla aspnet_Users, incluye aspnet_Membership un campo ApplicationId que vincula esta información a una partición de aplicación concreta.

Protección de contraseñas

La información de contraseña se almacena en la aspnet_Membership tabla. El SqlMembershipProvider permite almacenar contraseñas en la base de datos mediante una de las tres técnicas siguientes:

  • Borrado : la contraseña se almacena en la base de datos como texto sin formato. Desaconsejo encarecidamente el uso de esta opción. Si la base de datos está en peligro, ya sea por un hacker que encuentre una puerta trasera o un empleado descontento que tenga acceso a la base de datos, todas las credenciales de cada usuario están ahí para tomar.
  • Hash: las contraseñas se aplican mediante un algoritmo hash unidireccional y un valor de sal generado aleatoriamente. Este valor hash (junto con la sal) se almacena en la base de datos.
  • Cifrado: una versión cifrada de la contraseña se almacena en la base de datos.

La técnica de almacenamiento de contraseñas usada depende de la configuración de SqlMembershipProvider especificada en Web.config. Veremos cómo personalizar la configuración de SqlMembershipProvider en el paso 4. El comportamiento predeterminado es almacenar el hash de la contraseña.

Las columnas responsables de almacenar la contraseña se Password, PasswordFormat y PasswordSalt. PasswordFormat es un campo de tipo int cuyo valor indica la técnica utilizada para almacenar la contraseña: 0 para Borrado; 1 para Hash; 2 para Cifrado. PasswordSalt se asigna una cadena generada aleatoriamente independientemente de la técnica de almacenamiento de contraseñas utilizada; el valor de PasswordSalt solo se usa al calcular el hash de la contraseña. Por último, la columna Password contiene los datos de contraseña reales, ya sea la contraseña de texto sin formato, el hash de la contraseña o la contraseña cifrada.

En la tabla 1 se muestra el aspecto de estas tres columnas para las diversas técnicas de almacenamiento al almacenar la contraseña MySecret. .

Técnica de almacenamiento<_o3a_p /> Password<_o3a_p /> PasswordFormat<_o3a_p /> PasswordSalt<_o3a_p />
Borrar MySecret! 0 tTnkPlesqissc2y2SMEygA==
Con hash 2oXm6sZHWbTHFgjgkGQsc2Ec9ZM= 1 wFgjUfhdUFOCKQiI61vtiQ==
Cifrados 62RZgDvhxykkqsMchZ0Yly7HS6onhpaoCYaRxV8g0F4CW56OXUU3e7Inza9j9BKp 2 LSRzhGS/aa/oqAXGLHJNBw==

Tabla 1: valores de ejemplo para los campos relacionados con la contraseña al almacenar la contraseña MySecret!

Nota:

El algoritmo hash o cifrado concreto utilizado por el SqlMembershipProvider viene determinado por la configuración del elemento <machineKey>.

Almacenamiento de roles y asociaciones de roles

El marco de roles permite a los desarrolladores definir un conjunto de roles y especificar qué usuarios pertenecen a qué roles. Esta información se captura en la base de datos a través de dos tablas: aspnet_Roles y aspnet_UsersInRoles. Cada registro de la tabla aspnet_Roles representa un rol para una aplicación determinada. Al igual que la tabla aspnet_Users la tabla aspnet_Roles tiene tres columnas pertinentes para nuestra discusión:

  • RoleId
  • RoleName
  • ApplicationId

RoleId es la clave principal (y de tipo uniqueidentifier). RoleName es de tipo nvarchar(256). Y ApplicationId vincula la cuenta de usuario a una aplicación determinada en aspnet_Applications. Hay una restricción UNIQUE compuesta en las columnas RoleName y ApplicationId, lo que garantiza que en una aplicación determinada cada nombre de rol sea único.

La tabla aspnet_UsersInRoles actúa como una asignación entre usuarios y roles. Solo hay dos columnas, UserId y RoleId , y juntas componen una clave principal compuesta.

Paso 4: especificar el proveedor y personalizar su configuración

Todos los marcos que admiten el modelo de proveedor, como los marcos de pertenencia y roles, carecen de detalles de implementación y, en su lugar, delegan esa responsabilidad a una clase de proveedor. En el caso del marco de pertenencia, la clase Membership define la API para administrar cuentas de usuario, pero no interactúa directamente con ningún almacén de usuarios. En su lugar, los métodos Membership de clase entregan la solicitud al proveedor configurado; usaremos el SqlMembershipProvider. Cuando invocamos uno de los métodos de la clase Membership, ¿cómo sabe el marco de pertenencia delegar la llamada a la SqlMembershipProvider?

La clase Membership tiene una propiedad que contiene una referencia property Providers a todas las clases de registrados disponibles para su uso por el marco de membresía. Cada proveedor registrado tiene un nombre y un tipo asociados. El nombre ofrece una manera fácil de hacer referencia a un proveedor determinado en la colección Providers, mientras que el tipo identifica la clase de proveedor. Además, cada proveedor registrado puede incluir opciones de configuración. Los valores de configuración del marco de pertenencia incluyen passwordFormat y requiresUniqueEmail, entre muchos otros. Consulte la tabla 2 para obtener una lista completa de las opciones de configuración usadas por el SqlMembershipProvider.

El contenido de la propiedad Providers se especifica a través de los valores de configuración de la aplicación web. De forma predeterminada, todas las aplicaciones web tienen un proveedor denominado AspNetSqlMembershipProvider de tipo SqlMembershipProvider. Este proveedor de pertenencia predeterminado se registra en machine.config (ubicado en %WINDIR%\Microsoft.Net\Framework\v2.0.50727\CONFIG):

<membership>
 <providers>
 <add name="AspNetSqlMembershipProvider"
 type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" 
 connectionStringName="LocalSqlServer"
 enablePasswordRetrieval="false"
 enablePasswordReset="true"
 requiresQuestionAndAnswer="true"
 applicationName="/"
 requiresUniqueEmail="false"
 passwordFormat="Hashed"
 maxInvalidPasswordAttempts="5"
 minRequiredPasswordLength="7"
 minRequiredNonalphanumericCharacters="1"
 passwordAttemptWindow="10"
 passwordStrengthRegularExpression=""/>
 </providers> 
</membership>

Como se muestra en el marcado anterior, el elemento <membership> define las opciones de configuración del marco de pertenencia, mientras que el elemento secundario <providers> especifica los proveedores registrados. Los proveedores se pueden agregar o quitar mediante los elementos <add> o <remove>; use el elemento <clear> para quitar todos los proveedores registrados actualmente. Como se muestra en el marcado anterior, machine.config agrega un proveedor denominado AspNetSqlMembershipProvider de tipo SqlMembershipProvider.

Además de los atributos name y type , el elemento <add> contiene atributos que definen los valores de varias opciones de configuración. En la tabla 2 se enumeran los valores de configuración disponibles SqlMembershipProvider específicos, junto con una descripción de cada uno.

Nota:

Los valores predeterminados indicados en la tabla 2 hacen referencia a los valores predeterminados definidos en la clase SqlMembershipProvider. Tenga en cuenta que no todos los valores de configuración de AspNetSqlMembershipProvider corresponden a los valores predeterminados de la clase SqlMembershipProvider. Por ejemplo, si no se especifica en un proveedor de pertenencia, el valor requiresUniqueEmail predeterminado es true. Sin embargo, el AspNetSqlMembershipProvider invalida este valor predeterminado especificando explícitamente un valor de false.

Configuración<_o3a_p /> Descripción<_o3a_p />
ApplicationName Recuerde que el marco de pertenencia permite que un único almacén de usuarios se particione entre varias aplicaciones. Esta configuración indica el nombre de la partición de aplicación utilizada por el proveedor de pertenencia. Si este valor no se especifica explícitamente, se establece, en runtime, en el valor de la ruta de acceso raíz virtual de la aplicación.
commandTimeout Especifica el valor de tiempo de espera del comando SQL (en segundos). El valor predeterminado es 30.
connectionStringName Nombre de la cadena de conexión del elemento <connectionStrings> que se va a usar para conectarse a la base de datos del almacén de usuarios. Se requiere un valor.
description Proporciona una descripción fácil de usar del proveedor registrado.
enablePasswordRetrieval Especifica si los usuarios pueden recuperar su contraseña olvidada. El valor predeterminado es false.
enablePasswordReset Indica si los usuarios pueden restablecer su contraseña. Tiene como valor predeterminado true.
maxInvalidPasswordAttempts Número máximo de intentos de inicio de sesión incorrectos que pueden producirse para un usuario determinado durante el passwordAttemptWindow especificado antes de que el usuario esté bloqueado. El valor predeterminado es 5.
minRequiredNonalphanumericCharacters Número mínimo de caracteres no alfanuméricos que deben aparecer en la contraseña de un usuario. Este valor debe estar comprendido entre 0 y 128; el valor predeterminado es 1.
minRequiredPasswordLength Número mínimo de caracteres necesarios en una contraseña. Este valor debe estar comprendido entre 0 y 128; el valor predeterminado es 7.
name Nombre del proveedor registrado. Se requiere un valor.
passwordAttemptWindow Número de minutos durante los que se realiza un seguimiento de los intentos de inicio de sesión erróneos. Si un usuario proporciona credenciales de inicio de sesión no válidas maxInvalidPasswordAttempts veces dentro de esta ventana especificada, se bloquean. El valor predeterminado es 10.
PasswordFormat El formato de almacenamiento de contraseñas: Clear, Hashed o Encrypted. El valor predeterminado es Hashed.
passwordStrengthRegularExpression Si se proporciona, esta expresión regular se usa para evaluar la intensidad de la contraseña seleccionada del usuario al crear una cuenta nueva o al cambiar su contraseña. El valor predeterminado es una cadena vacía.
requiresQuestionAndAnswer Especifica si un usuario debe responder a su pregunta de seguridad al recuperar o restablecer su contraseña. El valor predeterminado es true.
requiresUniqueEmail Indica si todas las cuentas de usuario de una partición de aplicación determinada deben tener una dirección de correo electrónico única. El valor predeterminado es true.
type Especifica el tipo del proveedor. Se requiere un valor.

Tabla 2: configuración de pertenencia y SqlMembershipProvider

Además de AspNetSqlMembershipProvider, otros proveedores de pertenencia se pueden registrar en una aplicación por aplicación agregando un marcado similar al archivo de Web.config.

Nota:

El marco roles funciona de la misma manera: hay un proveedor de roles registrado predeterminado en machine.config y los proveedores registrados se pueden personalizar en una aplicación por aplicación en Web.config. Examinaremos el marco roles y su marcado de configuración en detalle en un tutorial futuro.

Personalización de la configuración de SqlMembershipProvider

El SqlMembershipProvider predeterminado (AspNetSqlMembershipProvider) tiene su atributo connectionStringName establecido en LocalSqlServer. Al igual que el proveedor de AspNetSqlMembershipProvider, el nombre de la cadena de conexión LocalSqlServer se define en machine.config.

<connectionStrings> 
 <add name="LocalSqlServer" 
 connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" 
 providerName="System.Data.SqlClient"/> 
</connectionStrings>

Como puede ver, esta cadena de conexión define una base de datos de SQL 2005 Express Edition ubicada en |DataDirectory|aspnetdb.mdf'. Cadena |DataDirectory| se traduce en tiempo de ejecución para que apunte al directorio ~/App_Data/, por lo que la ruta de acceso de la base de datos |DataDirectory|aspnetdb.mdf" se traduce en ~/App_Data/aspnet.mdf.

Si no especificamos ninguna información del proveedor de pertenencia en el archivo Web.config de la aplicación, la aplicación usa el proveedor de pertenencia registrado predeterminado, AspNetSqlMembershipProvider. Si la base de datos ~/App_Data/aspnet.mdf no existe, el runtime de ASP.NET lo creará automáticamente y agregará el esquema de servicios de aplicación. Sin embargo, no queremos usar la base de datos aspnet.mdf; en su lugar, queremos usar la base de datos SecurityTutorials.mdf que creamos en el paso 2. Esta modificación se puede realizar de una de estas dos maneras:

  • Especifique un valor para el nombre de la cadena de conexión LocalSqlServerenWeb.config. Al sobrescribir el valor de nombre de la cadena de conexión de LocalSqlServer en Web.config, podemos usar el proveedor de pertenencia registrado predeterminado (AspNetSqlMembershipProvider) y hacer que funcione correctamente con la base de datos SecurityTutorials.mdf. Este enfoque es correcto si se trata de contenido con las opciones de configuración especificadas por AspNetSqlMembershipProvider. Para obtener más información sobre esta técnica, consulte la entrada de blog de Scott Guthrie: Configuración de los servicios de aplicaciones ASP.NET 2.0 para utilizar SQL Server 2000 o SQL Server 2005 .
  • Agregue un nuevo proveedor registrado de tipoSqlMembershipProvidery configure su valorconnectionStringNamepara que apunte a la base de datosSecurityTutorials.mdf. Este enfoque es útil en escenarios en los que desea personalizar otras propiedades de configuración además de la cadena de conexión de la base de datos. En mis propios proyectos siempre uso este enfoque debido a su flexibilidad y legibilidad.

Para poder agregar un nuevo proveedor registrado que haga referencia a la base de datos SecurityTutorials.mdf, primero es necesario agregar un valor de cadena de conexión adecuado en la sección <connectionStrings> de Web.config. El marcado siguiente agrega una nueva cadena de conexión denominada SecurityTutorialsConnectionString que hace referencia a la base de datos SecurityTutorials.mdf de SQL Server 2005 Express Edition en la carpeta App_Data.

<configuration>
 <connectionStrings>
 <add name="SecurityTutorialsConnectionString" 
 connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\SecurityTutorials.mdf;Integrated Security=True;User Instance=True" 
 providerName="System.Data.SqlClient"/> 
 </connectionStrings> 
 <system.web>
 ... Configuration markup  removed for brevity ... 
 </system.web>
</configuration>

Nota:

Si usa un archivo de base de datos alternativo, actualice la cadena de conexión según sea necesario. Para obtener más información sobre cómo formar la cadena de conexión correcta, consulte ConnectionStrings.com.

A continuación, agregue el siguiente marcado de configuración de pertenencia al archivo Web.config. Este marcado registra un nuevo proveedor denominado SecurityTutorialsSqlMembershipProvider.

<configuration> 
 <connectionStrings>
 <add name="SecurityTutorialsConnectionString" 
 connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\SecurityTutorials.mdf;Integrated Security=True;User Instance=True" 
 providerName="System.Data.SqlClient"/>
 </connectionStrings> 
 <system.web>
 <membership defaultProvider="SecurityTutorialsSqlMembershipProvider">
 <providers>
 <!--Add a customized SqlMembershipProvider --> 
 <add name="SecurityTutorialsSqlMembershipProvider" 
 type="System.Web.Security.SqlMembershipProvider"
 connectionStringName="SecurityTutorialsConnectionString"
 enablePasswordRetrieval="false"
 enablePasswordReset="true"
 requiresQuestionAndAnswer="true"
 applicationName="SecurityTutorials"
 requiresUniqueEmail="true"
 passwordFormat="Hashed"
 maxInvalidPasswordAttempts="5"
 minRequiredPasswordLength="7"
 minRequiredNonalphanumericCharacters="1"
 passwordAttemptWindow="10"
 passwordStrengthRegularExpression=""/>
 </providers>
 </membership>
 ... Configuration markup removed for brevity ... 
 </system.web>
</configuration>

Además de registrar el proveedor SecurityTutorialsSqlMembershipProvider, el marcado anterior define el SecurityTutorialsSqlMembershipProvider como proveedor predeterminado (a través del atributo defaultProvider en el elemento <membership>). Recuerde que el marco de pertenencia puede tener varios proveedores registrados. Dado que AspNetSqlMembershipProvider se registra como el primer proveedor de machine.config, actúa como proveedor predeterminado a menos que se indique lo contrario.

Actualmente, nuestra aplicación tiene dos proveedores registrados: AspNetSqlMembershipProvider y SecurityTutorialsSqlMembershipProvider. Sin embargo, antes de registrar el proveedor SecurityTutorialsSqlMembershipProvider podríamos haber borrado todos los proveedores registrados anteriormente agregando un elemento <clear /> inmediatamente antes de nuestro elemento <add>. Esto borraría el AspNetSqlMembershipProvider de la lista de proveedores registrados, lo que significa que el SecurityTutorialsSqlMembershipProvider sería el único proveedor de pertenencia registrado. Si usamos este enfoque, no sería necesario marcar el SecurityTutorialsSqlMembershipProvider como proveedor predeterminado, ya que sería el único proveedor de pertenencia registrado. Para obtener más información sobre el uso de <clear />, consulte Uso de <clear /> al agregar proveedores.

Tenga en cuenta que el valor de connectionStringName de SecurityTutorialsSqlMembershipProvider hace referencia al nombre de la cadena de conexión SecurityTutorialsConnectionString recién agregado y que su configuración applicationName se ha establecido en un valor de SecurityTutorials. Además, la configuración de requiresUniqueEmail se ha establecido en true. Todas las demás opciones de configuración son idénticas a los valores de AspNetSqlMembershipProvider. No dude en realizar modificaciones de configuración aquí, si lo desea. Por ejemplo, puede reforzar la seguridad de la contraseña al requerir dos caracteres no alfanuméricos en lugar de uno, o aumentando la longitud de la contraseña a ocho caracteres en lugar de siete.

Nota:

Recuerde que el marco de pertenencia permite que un único almacén de usuarios se particione entre varias aplicaciones. La configuración applicationName del proveedor de pertenencia indica qué aplicación usa el proveedor al trabajar con el almacén de usuarios. Es importante establecer explícitamente un valor para la configuración applicationName porque si el applicationName no está establecido explícitamente, se asigna a la ruta de acceso raíz virtual de la aplicación web en runtime. Esto funciona bien siempre que la ruta de acceso raíz virtual de la aplicación no cambie, pero si mueve la aplicación a otra ruta de acceso, la configuración de applicationName también cambiará. Cuando esto sucede, el proveedor de pertenencia comenzará a trabajar con una partición de aplicación diferente de la usada anteriormente. Las cuentas de usuario creadas antes del traslado residirán en una partición de aplicación diferente y esos usuarios ya no podrán iniciar sesión en el sitio. Para obtener una explicación más detallada sobre este tema, vea Establecer siempre la propiedad applicationName al configurar ASP.NET 2.0 pertenencia y otros proveedores.

Resumen

En este momento tenemos una base de datos con los servicios de aplicación configurados (SecurityTutorials.mdf) y hemos configurado nuestra aplicación web para que el marco de pertenencia use el proveedor SecurityTutorialsSqlMembershipProvider que acabamos de registrar. Este proveedor registrado es de tipo SqlMembershipProvider y tiene su connectionStringName establecido en la cadena de conexión adecuada (SecurityTutorialsConnectionString) y su valor applicationName establecido explícitamente.

Ahora estamos listos para usar el marco de pertenencia de nuestra aplicación. En el siguiente tutorial examinaremos cómo crear nuevas cuentas de usuario. Después de eso, exploraremos la autenticación de los usuarios, la realización de la autorización basada en el usuario y el almacenamiento de información adicional relacionada con el usuario en la base de datos.

¡Feliz programación!

Lecturas adicionales

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

Entrenamiento en vídeo sobre temas incluidos en este tutorial

Acerca del autor

Scott Mitchell, autor de varios libros de ASP/ASP.NET y fundador de 4GuysFromRolla.com, ha estado trabajando 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. Se puede contactar con Scott en mitchell@4guysfromrolla.com o a través de su blog en http://ScottOnWriting.NET.

Agradecimientos especiales a

Esta serie de tutoriales contó con la revisión de muchos revisores que fueron de gran ayuda. La revisora principal de este tutorial era Alicja Maziarz. ¿Le interesaría revisar mis próximos artículos de MSDN? Si es así, escríbame a mitchell@4GuysFromRolla.com.