Twitter Facebook RSS Feed

lunes, 19 de octubre de 2009 a las 10:59hs por Dario Krapp

Evolución

Este modo de funcionamiento que hemos visto, propio de las versiones 1.x del Framework fue mejorado en la versión 2.0 donde se introdujeron cambios que permitieron automatizar ya no solo la autenticación contra cualquier repositorio, sino que también las operaciones (creación, modificación, eliminación, cambios de clave, etc.) de los usuarios involucrados en la misma, lo cual es bastante bueno ya que esas tareas son en realidad también bastante repetitivas.

Todos estos avances pudieron realizarse gracias al esquema de membrecía, más conocido como Membership (En el Framework 2.0 Se ha incluido además de la membrecía, la posibilidad de utilizar roles y perfiles de usuario).

La membrecía además de ofrecer código desarrollado, testeado y mantenido para el manejo de usuarios, brinda la posibilidad de utilizar controles ya incluidos en ASP.NET para realizar una variada cantidad de operaciones y la posibilidad de utilizar como repositorios un motor de base de datos SQL Server, Active Directory o un repositorio personalizado (donde deberá obviamente incluirse el código necesario para su funcionamiento). El siguiente esquema muestra a los actores involucrados y como los mismos se relacionan.


Niveles del Membership
En el esquema puede observarse la existencia de los niveles: repositorios, proveedores, API de membrecía y controles incluidos en ASP.NET relacionados con la membrecía.

El primer nivel (repositorios) hace referencia al lugar donde la información de membrecía será almacenada. El segundo nivel (proveedores) está compuesto por clases dentro del Framework con la capacidad de establecer un enlace entre los repositorios del nivel inferior y la API del nivel superior.

El tercer nivel estará compuesto por la API de membrecía y el último nivel constituido por controles ya existentes en ASP.NET capaces de realizar las operaciones de membrecía y autenticación más frecuentes.
Bajo este esquema de funcionamiento la API en el tercer nivel podrá utilizar cualquier proveedor sin importar su implementación ya que todos los proveedores heredarán una clase en común llamada ProviderBase, brindándole a la API los miembros necesarios para que la misma pueda operar unívocamente con cualquiera de ellos.

Para el caso de SQL Server y Active Directory las implementaciones ya se encontrarán desarrolladas mientras que para realizar otras implementaciones será necesario crear una clase que herede de ProviderBase y se deberán sobreescribir los métodos necesarios apropiadamente.

En nuestro ejemplo utilizaremos como repositorio un motor SQL Server 2008 Enterprise Edition y como la implementación del proveedor SQL Server ya se encuentra desarrollada, simplemente deberemos preparar el repositorio y establecer el proveedor para que la API de membrecía lo utilice.

Antes que nada limpiaremos las líneas que habíamos agregado en el archivo web.config y dejaremos solo las siguientes:

<authentication mode="Forms">
  <forms loginUrl="ingreso1.aspx"/>
</authentication>
<authorization>
  <deny users="?"/>
</authorization>

El primer paso, como mencionamos previamente es el de preparar el repositorio, y considerando que estamos utilizando la opción de SQL Server, esto significará crear la base de datos, tablas, procedimientos almacenados, funciones, etc. para cada uno de los servicios que utilizararemos, para ser consistentes con la terminología utilizada, denominaremos a la membrecía como un servicio que instalaremos sobre el repositorio, (aunque en nuestro caso serán un conjunto de componentes de bases de datos). Además del servicio de membrecía existen otros servicios que también pueden instalarse, como indicaremos a continuación.

Un detalle es que en el caso de SQL Server Express 2005, el proveedor (SqlMembershipProvider) será capaz de instalar el servicio de membrecía automáticamente, pero en nuestro caso deberemos efectuar la tarea manualmente, aunque no es muy desalentador ya que la misma podrá efectuarse ejecutando por línea de comandos un comando llamado aspnet_regsql ajustando sus parámetros según nuestras necesidades. A continuación se describen los parámetros disponibles:

  • -S : Nombre del servidor/instancia SQL Server que deberá ser de la versión 7.0 o superior
  • -U: nombre de usuario
  • -P:Clave del usuario
  • -E: indicará específicamente que se utilizará autenticación integrada vía Windows, por lo que se omitirán los parámetros U y P. Cabe considerarse que si los parámetros U y P no son establecidos el comando asumirá automáticamente la autenticación vía Windows.
  • -C: permitirá establecer el string de conexión ya sea por OLEDB u ODBC
  • -sqlexportonly: Creará los scripts pero no los ejecutará.
  • -A: Indicará que servicios deberán agregarse al repositorio, los cuales son membrecía, roles, perfiles, personalización para páginas con web parts y proveedor de eventos.Es posible instalar todos los servicios a la vez utilizando la opción all o cada servicio individualmente utilizando las opciones m, r, p, c y w para las opciones de membrecía, roles, perfiles, web parts y eventos respectivamente, en este articulo veremos la opción de membrecía y haremos algunos comentarios sobre la opción de roles.
  • -R: Indica que servicios deberán removerse, en contraposición a la opción A y acepta las mismas opciones (all, m, r, p, c y w)
  • -d: permite definir el nombre de la base de datos donde se instalarán los servicios. Tomándose el nombre aspnetdb por defecto.

Para nuestro ejemplo ejecutaremos el comando de la siguiente forma:


Linea de comandos - Membership
Se ha utilizado la dirección:

<unidad:>\WINDOWS\Microsoft.NET\Framework\v2.0.50727

Ya que la versión 3.0 y 3.5 son en realidad upgrades de la versión 2.0 por lo que el archivo aspnet_regsql no se encontrará en carpetas de versiones posteriores, debido a que no ha sido modificado desde la versión 2.0.

Para la utilización de membrecía será suficiente definir el parámetro –A con el valor “m”, esto indicaría que solo instalaremos los servicios de membrecía. Hemos incluido también los servicios de roles (letra “r”), como comentamos previamente, por que haremos unas referencias adicionales en el artículo.

Si luego ingresamos a nuestro servidor de base de datos veremos que el comando ha creado la base de datos pruebamembership y la estructura que el proveedor SqlMembershipProvider utilizará.
Si el archivo aspnet_regsql es ejecutado sin parámetros, se mostrará un asistente (Wizard) que permitirá configurar los parámetros que hemos visto previamente en una ventana visualmente.

Con el repositorio construido, el segundo paso será configurar a ASP.NET para que utilice el repositorio, esto implica hacer que ASP.NET utilice el proveedor SqlMembershipProvider con la configuración de acceso a la base de datos que hemos creado. Este paso es bastante simple y consta de crear una cadena de conexión y configurar el proveedor. Por simplicidad, he definido la cadena de conexión desde las propiedades del proyecto de la siguiente forma:


ConnectionString Membership

Luego de haberse definido la cadena de conexión deberá configurarse el proveedor para que utilice esa cadena de conexión. Esta tarea se realizará dentro del mismo archivo web.config y constará en definir los tags membership y provider (dentro de system.web).

En nuestro caso utilizaremos la siguiente configuración:

<membership defaultProvider="PruebamembershipProvider">
  <providers>
    <add name="PruebamembershipProvider"  connectionStringName="FAYMS.Properties.Settings.pruebamembership"
        applicationName=" Pruebamembership 1"
        enablePasswordRetrieval="false"
        enablePasswordReset="true"
        requiresQuestionAndAnswer="false"
        requiresUniqueEmail="false"
        passwordFormat="Hashed"
        minRequiredPasswordLength="4"
        minRequiredNonalphanumericCharacters="0"
        type="System.Web.Security.SqlMembershipProvider" />
   </providers>
</membership>

En estas líneas hemos agregado a la membrecía el proveedor que hemos llamado PruebamembershipProvider que es del tipo SqlMembershipProvider y utiliza la conexión FAYMS.Properties.Settings.pruebamembership (que es la conexión que hemos definido desde las propiedades del proyecto previamente).

Para cada proveedor existirá además de los dos parámetros que hemos comentado una gran variedad de parámetros de configuración, que determinarán el comportamiento del mismo, para quien esté interesado en conocer todas las posibilidades, les dejo el siguiente enlace:

Propiedades de SqlMembershipProvider

Una vez realizados estos pasos la membrecía ha quedado terminada y lista para su uso.

Visual Studio ofrecerá incluso una herramienta denominada Web Site Administration Tool o simplemente WAT capaz entre otras cosas de operar con proveedores de membrecía. Si deseamos por ejemplo crear un usuario sobre el proveedor que hemos definido recientemente (PruebamembershipProvider) simplemente deberemos seleccionar la opción ASP.NET Configuration del Menú Project y aparecerá la aplicación WAT como se muestra a continuación:


WAT1
Si seleccionamos la opción Security


WAT2
Podremos por ejemplo crear un nuevo usuario seleccionando la opción Create user, donde un formulario de alta de usuarios se mostrará en pantalla, el comportamiento del mismo dependerá de las opciones parametrizadas en el proveedor. En nuestro caso según los parámetros configurados tomará el siguiente formato:


WAT3
El botón Create User Creará el usuario en el repositorio, como puede verse a continuación:


Membership DB2
Si dentro de la WAT cliqueamos la solapa Provider y la opción Select a different provider for each feature (advanced) veremos que se encuentra el proveedor que hemos definido junto al proveedor por defecto.


WAT4

Nuestro proveedor ha quedado seleccionado ya que de esa forma lo hemos definido en el atributo defaultProvider del tag membership, en cuanto al proveedor ya incluido en ASP.NET que puede verse en la imagen, que no utilizaremos en nuestro ejemplo, podremos removerlo de la siguiente forma:

<membership defaultProvider="PruebamembershipProvider">
  <providers>
    <remove name="AspNetSqlMembershipProvider" />
    <add name="PruebamembershipProvider"
    ……..

Luego de tanto trabajo, aunque sin una sola línea de código, lo mínimo que esperaríamos es poder autenticar a Usuario1 tal como lo habíamos hecho hace unos cuantos párrafos atrás sin el uso de membrecía.
Si en la antigua pantalla de Ingreso1.aspx modificamos el código de siguiente forma:

protected void Login_Click(object sender, EventArgs e)
        {
            if (Membership.ValidateUser(Usuario.Text, Clave.Text))
                FormsAuthentication.RedirectFromLoginPage(Usuario.Text, false);
            else
                LabelError.Text = "Usuario o clave incorrecto";
        }

Y luego intentamos ingresar, veremos que todo funcionará según lo esperado. Como podemos ver, la validación del usuario ahora se efectuará mediante la API de membrecía, mientras que el manejo de la autenticación seguirá bajo el control de la clase FormsAuthentication.

La API de membrecía ofrecerá un amplio conjunto de métodos, además de ValidateUser se encontrarán CreateUser, DeleteUser, FindUsersByEmail, FindUsersByName, GeneratePassword, GetAllUsers, GetNumberOfUsersOnline, GetUser, GetUserNameByEmail y UpdateUser, donde sus nombres definen claramente su funcionalidad. La API de membrecía también ofrecerá unas cuantas propiedades y el evento ValidatingPassword que se disparará cuando un usuario es creado o su clave es modificada o reestablecida (reset).

Un objeto del tipo MembershipUser será devuelto por el método GetUser y mientras que un MembershipUserCollection será devuelto en los métodos FindUsersByEmail, FindUsersByName y GetAllUsers. La clase MembershipUser permitirá obtener información del usuario que representa (como por ejemplo: Nombre de usuario, Email, etc.) a través de sus propiedades. MembershipUser también contendrá métodos para realizar algunas operaciones como por ejemplo restablecer la clave de un usuario (reset) o modificarla.

Vuelvo a insistir en el hecho de que una ventaja muy interesante de la implementación de membrecía es que el uso de herencia y configuraciones en el web.config ha permitido un alto nivel de abstracción, el método ValidateUser de la clase Membership desconoce sobre que repositorio se está trabajando. Este desacople entre la API de membrecía y el manejo de los repositorios ha dado lugar a la creación de controles capaces de efectuar operaciones rutinarias de membrecía y autenticación en forma automática. Todo el esquema de autenticación que habíamos organizado en la página Ingreso1.aspx podrá reemplazarse con un solo control incluido ASP.NET y llamado adecuadamente Login.

Si reemplazamos los controles que habíamos agregado en la página Ingreso1.aspx por lo siguiente:

<asp:Login 
        runat="server" 
        ID="Login1" 
        RememberMeText="Recordar" 
        UserNameLabelText="Usuario" 
        PasswordLabelText="Clave"   
        TitleText="Ingreso a la aplicación" 
        FailureText="Usuario o clave incorrecto"
        LoginButtonText="Ingresar" 
        DisplayRememberMe="true">
</asp:Login>

Obtendremos el mismo resultado con la ventaja de validadores incorporados, la opción de recordar al usuario incluida, código testeado, mantenido y listo para usar. Otros controles incorporados son LoginStatus, LoginView, PasswordRecovery, ChangePassword y el interesante CreateUserWizard cuyos nombres nos dan una idea inequívoca de sus funcionalidades.

Ahora que hemos conseguido hacer andar a la autenticación, posiblemente será un buen momento para retomar un detalle que habíamos dejado sujeto con alfileres, el cual es el tag authorization. En su momento lo definimos de la siguiente forma:

<authorization>
  <deny users="?"/>
</authorization>

Donde indicábamos que los usuarios anónimos debían denegarse. El formato general del tag es el siguiente:

<authorization>
  <[allow|deny] users roles verbs />
</authorization>

Donde los tags allow o deny representarán reglas de acceso( a través de las operaciones de “permitir” o “denegar”) a los recursos del sitio. El atributo users representará a un grupo de usuarios y aceptará cuentas de usuario tanto como los simbolos “?” y “*” representando el símbolo “?” a los usuarios anónimos (no logueados) y “*” a todos los usuarios, de tal forma al especificar:

<deny users="?"/>

Se estaba indicando que se denegara el acceso a los recursos del sitio a usuarios anónimos, bajo estas circunstancias, cuando el browser intentase acceder a la página Default.aspx que es específicamente un recurso dentro de la carpeta principal del sitio, con un usuario aún no autenticado, el acceso sería denegado.

Es claro que en ningún lado especificamos que si debe permitirse el acceso a usuarios autenticados, la forma de especificarlo explícitamente sería la siguiente:

<authorization>
  <deny users="?"/>
  <allow users="*"/>
</authorization>

Esto implica en primer lugar que es posible utilizar varios tag allow o deny como reglas de acceso, en segundo lugar que son procesados en orden, o sea la regla deny se aplica primero, y para quienes hayan superado la regla luego se aplicará la regla allow (si invirtiéramos las reglas veríamos que cualquier usuario podría ingresar al sitio dejando a la regla deny posterior sin sentido) y en tercero y último lugar, esto implica que existe un allow * implícito (solo es necesario acceder a

<unidad:>\WINDOWS\Microsoft.NET\Framework\v2.0.50727\config\web.config

para confirmarlo, comentario aparte, en este archivo se movieron algunas cuantas definiciones existentes en el archivo machine.config de las versiones 1.x), por ese motivo si eliminamos el tag authorization cualquier usuario podrá ingresar y también podremos omitir el tag allow que escribimos explícitamente en el último ejemplo.
De forma similar podríamos haber utilizado la regla:

<authorization>
  <allow users="Usuario1"/>
  <deny users="*"/>
</authorization>

Si agregamos nuevos usuarios, además de Usuario1 que ya existía previamente e intentamos ingresar a Default.aspx veremos que solo Usuario1 puede hacerlo, los intentos con otros usuarios fallarán, y esto es lo que hemos especificado en las reglas de autorización, primero permitir el acceso al recurso pedido para Usuario1, y de quienes no cumplan la regla primera, ejecutar la segunda regla, que indica que para todos ellos, negar el acceso al recurso. Es posible incluir a varios usuarios separados por coma en el atributo users y evitarnos escribir unos cuantos tags.

Las reglas de autorización regirán para la carpeta del sitio tanto como para las subcarpetas del mismo, supongamos por ejemplo que nuestro sitio posee una subcarpeta de imágenes como se muestra en el ejemplo:


Estructura del proyecto 2

Y en nuestra página de login, Ingreso1.aspx agregamos lo siguiente:

<asp:Image runat="server" ImageUrl="Images/Logo.png" />

Si intentamos navegar la página Default.aspx seremos redireccionados a la página de login (esto se ha vuelto tan repetitivo que ya no debería sorprendernos) pero lo interesante es que veremos que la imagen aparece como inexistente en el browser aunque es claro que si existe.


Autenticación 2
Lo que sucede es que la imagen es también un recurso del sitio y la subcarpeta Images ha heredado las reglas de la carpeta padre, donde se establecía denegar el acceso a los usuarios no autenticados. Quien lo dude podrá simplemente probar autenticarse y luego volver a la página Ingreso1.aspx (sin desautenticarse) y la imagen aparecerá.
Es posible modificar las propiedades de las subcarpetas utilizando un tag llamado location, para nuestro ejemplo deberíamos escribir lo siguiente:

<location path="Images">
  <system.web>
    <authorization>
      <allow users="*"/>
    </authorization>
  </system.web>
</location>

El tag Location debemos definirlo dentro del tag Configuration y al mismo nivel del tag system.web del sitio y el mismo permitirá sobreescribir cualquier definición. En particular, para nuestro caso hemos sobreescrito la definición de autorización para que todo usuario pueda acceder a los recursos de la carpeta Images.

Además del atributo Users existe otro atributo llamado Verb en el tag authorization, que es opcional y permitirá especificar si la regla se aplicará a alguna acción de las siguientes GET, HEAD y POST. Por defecto el valor es “*” (para las tres acciones).

Finalmente veremos que existe la posibilidad de utilizar un atributo llamado roles (no es posible utilizar los atributos roles y users simultáneamente), la forma de uso es equivalente a los usuarios pero viendo esto podríamos preguntarnos ¿qué es un rol?.

Previamente habíamos comentado que el framework ofrecía además la posibilidad de incluir roles para los usuarios, la cual será seguramente una opción muy usual en escenarios de mundo real, comentaremos brevemente como utilizar roles con autenticación por formularios.

Para incluir roles en el esquema que hemos visto se ha adoptado una filosofía similar a la membrecía. Existirá en lugar de una API de membrecía una API de roles y un proveedor de roles, para nuestro caso, donde el repositorio era un servidor SQL Server 2008 Enterprise edition, en la creación del mismo, con la ayuda del comando aspnet_regsql hemos incluido los servicios de roles (incluyendo en el parámetro “-A” el valor “r”), así que solamente deberemos definir el proveedor de roles en el archivo web.config de la siguiente forma:

<roleManager enabled="true" defaultProvider="PruebaRolProvider">
  <providers>
    <remove name="AspNetSqlRoleProvider" />
    <add connectionStringName="FAYMS.Properties.Settings.pruebamembership"
          applicationName="PruebaRol1" name="PruebaRolProvider" type="System.Web.Security.SqlRoleProvider" />
  </providers>
</roleManager>

Desde la WAT encontraremos una sección para el manejo de roles e inclusión de usuarios en los mismos. La API de roles por otra parte nos permitirá realizar varias tareas programáticamente. La ventaja de los roles radica en que se simplificarán las tareas de autorización y configuración de permisos, al igual que sucede en el propio sistema operativo.

Después de tanto visto, habrá seguramente quien se haya percatado de un detalle incómodo, ya que por lo visto hasta ahora hay ciertos datos del usuario (como por ejemplo el mail del mismo) que se encuentran incluidos en este esquema, pero es de esperarse que en cualquier escenario real puedan existir otros datos no hayan sido contemplados, y esta situación es inevitable ya que las posibilidades parecen infinitas. Por ejemplo, en algún tipo de aplicación podría requerirse almacenar el peso o la altura del usuario (para dar un ejemplo simple). Los perfiles o Profiles permitirán incluir información personalizada de los usuarios de la aplicación y una característica interesante es que este servicio no está ligado solamente a la autenticación por formularios, aunque como es de esperarse, funcionará perfectamente con ella. Los perfiles son tema bastante extenso del cual espero, podamos escribir algún artículo posteriormente, pero quería al menos comentar su existencia para que quién los necesite pueda desde este punto continuar investigando de qué se trata el tema.

39 comentarios »

  1. epifannio dice:

    Excelente guia funciona perfectamente, un detalle como se puede direccionar a una pagina .aspx específica de acuerdo al tipo de usuario despues de autenticarse?

  2. Dario Krapp dice:

    Muchas gracias Epifannio, el tema es que generalmente un usuario intenta acceder a una página y luego de la autenticación deseará ir a la pagina que había solicitado originalmente, a menos que haya ingresado a la página de login.
    Para hacer que un usuario según alguna condición vaya a una página determinada, la forma que me parece de hacerlo es la siguiente:

                if (Membership.ValidateUser("Usuario1", "Usuario1"))
                {
                    FormsAuthentication.SetAuthCookie("Usuario1", false);
                    if (Roles.IsUserInRole("Usuario1", "Rol1"))
                        Response.Redirect("Default2.aspx");
                    else
                        Response.Redirect("Default3.aspx");
                }

    El usuario y clave están hardcodeados en este ejemplo para simplificarlo. El único punto a mencionar es que debés utilizar el método SetAuthCookie de la clase estática FormsAuthentication para establecer la cookie de autenticación (el segundo parámetro indicará si la cookie será o no persitetnte).
    En este ejemplo si el usuario pertenece al rol “Rol1” es redirigido a la pagina “Default2.aspx” y el caso contrario a “Default3.aspx”, pero la condición puede definirse según las necesidades de la aplicación.
    Espero que la respuesta te haya servido.

  3. epifannio dice:

    ok gracias Dario, en un tema que google no me ayudó bastante bien como tú es: Cómo imprimir los datos de un formulario web en asp.net? y mejor si es solo datos por que en los papeles membretados solo hace falta llenar campos vacios al imprimir.

    Te cuento que cuando le doy con “window.print() de javascript” me imprime con cabeceras, pies, botones de la página.

    Dario muchas gracias por tu ayuda..

    • Epiffanio:
      Para elegir que imprimir y que no de una página web puedes utilizar estilos, la clave es crear estilos distintos para lo que no quieras imprimir. Por ejemplo, supongamos que tenemos una página con un cuadro de texto y un botón, y sólo quieres que se imprima el cuadro de texto:

      <INPUT TYPE="text" name="texto" value="Prueba" />
      <INPUT TYPE="submit" value="enviar"/>

      Para que el segundo control no se imprima puedes crear un estilo dentro del medio “print”, para que sólo se aplique al imprimir:

      @media print
      {
          .noPrint
          {
              display: none;
          }
      }
      
      BODY
      {
          overflow: hidden;
      .....

      Entonces, nuestro código HTML quedaría así:

      <INPUT TYPE="text" name="texto" value="Prueba" />
      <INPUT TYPE="submit" value="enviar" class="noPrint" />

      Si te fijas en el botón verás que le apliqué el estilo “noPrint” que, en el medio “Print”, hace que no se vea. Ten en cuenta que si quieres aplicar varios estilos a un mismo control puedes hacerlo separando los nombres con espacios, por ejemplo: ‘class=”noPrint botonAzul”‘.
      Espero que se entienda la explicación, cualquier otra duda te invito a nuestro foro donde intentaremos responderte a la brevedad: http://foro.scientia.com.ar.
      Suerte!

  4. pueden hacerlo en visual xfis n.n graxias

  5. julio dice:

    Muy buen artículo. Muy bien explicado, me ha sido de mucha ayuda para comenzar en este tema. Saludos!

  6. Oscar Perez dice:

    Muy buena la explicacion.

    Tengo una pregunta: Podria delegar la autorizacion de una aplicacion (www.primer.com) en otra aplicacion (https://validar.net) y seguir trabajando en el primer sitio? Tambien si necesito redirigir a un tercer dominio seguro lo pueda hacer (www.tercero.com) ?

    • Dario Krapp dice:

      Hola Oscar, muchas gracias.

      Lamentablemente no creo que puedas delegar la autenticación en otro sitio con Forms authentication, lo que sucederia es que al loguearte exitosamente en el sitio “validar.net” el mismo va a generar una cookie encriptada en el browser guardando informacion (entre otras cosas) del logueo, esta infomacion es la que chequea el método de consulta de autenticacion que proporciona ASP.NET para consultar si un usuario está autenticado, pero cuando quieras leerlo desde otro sitio, por ejemplo “primer.com” este sitio no va a poder acceder a las cookies del primero, esto esta hecho así por seguridad y es un mecanismo que asegura que no puedas leer informacion de autenticacion de otros sitios desde el tuyo.

      Creo que deberias tomar otro enfoque para lograr esto, una posibilidad es la autenticacion delegada y una opcion es utilizar Open ID, podes encontrar una implementacion en el siguiente link

      http://www.ohloh.net/p/dotnetopenauth/

      Por otra parte Microsoft ya posee una implementacion lista para usar, en este caso Microsoft ofrece toda la plataforma necesaria para realizar la autenticacion delegada y se encarga de guardar las credenciales en servidores propios, podés encontrar información en http://www.passport.net/ .Además de Microsoft hay otras empresas que ofrecen servicios similares.
      Espero que esto te sea de ayuda. Suerte!!!

  7. Adyir dice:

    Hola como estas… Esta muy completo e interesante el post. Desde hace tiempo tengo una duda que no he podido aclarar. Que pasa si yo agarro la cookie de una pc autenticada y la copia a otra pc? Estaria autenticado igual o es valida solo para la maquina donde se creo?
    Es que hay ataques de hackers donde roban las cookies

    • Dario Krapp dice:

      Hola Adyir, es una buena pregunta, nunca he probado hacer esto que comentás, pero en teoría debería funcionar. El tema es que deberías poder tener el acceso a las cookies de una pc autenticada, lo cual seria en sí ya un problema de seguridad.
      Slds

  8. Rigo dice:

    Hola Dario, excelente articulo, solo una pregunta:

    Si deseo autenticar los usuarios registrados en una base de datos, que debo de hacer, ya lo hice mediante variables de Session, pero no me parece que sea lo mejor.

    • Dario Krapp dice:

      Hola Rigo, muchas gracias.
      Creo que es lo mejor evitar el uso de variables de sesión, obviamente dependiendo la cantidad de usuarios concurrentes, la información que se guarde en sesion y como las variables de sesión se utilicen, las mismas pasarán de ser algo poco desable pero sin mayores consecuencias a un problema que impedirá el uso de la aplicacíon, con todas las gamas intermedias entre estos extremos.
      Parte del artículo trata de como autenticar usuarios de una base de datos mediante Forms Authentication, utilizando estas funcionalidades la aplicación no utilizará variables de sesión sino que utilizará cookies encriptadas.

  9. kory23 dice:

    Hola
    Quisiera ver si me puedes dar una idea de cómo extraer las credenciales de windows?.
    Necesito hacer un aplicación para acceder a aplicaciones, pero que valide que si ya estoy logueado con las credenciales de windows no me pida ni usuario ni contraseña.
    Para acceder a dichas aplicaciones lo hago desde SharePoint.

    Saludos!

  10. Paris escort dice:

    ¿Te importa si cito a algunos de sus artículos todo el tiempo que proporcionar crédito y las fuentes de nuevo a su sitio? Mi sitio está en el nicho mismo que el suyo y mis usuarios realmente se beneficiaría de una gran parte de la información que usted proporciona aquí. Por favor , hágamelo saber si esta bien para ti . ¡Gracias! deseo suerte !

  11. Juan Cruz dice:

    Gran comentario se agradece el tema

  12. Juan Cruz dice:

    Buen Tema amigo

  13. Angel Guerrero dice:

    Al momento que agrego la seccion de roles me aparece este error “Las secciones sólo deben aparecer una vez en cada archivo de configuración. Consulte el tema de ayuda sobre las excepciones”, modifique cadenas de conexión y nombres pero continua el mensaje, me podrias ayudar un poco

    • Dario Krapp dice:

      Hola Angel,

      Este error que nos comentás es un problema de tag duplicado en el web.config, por ejemplo, la siguiente configuración en el archivo web.config generará un error similar:

      <system.web>
          <authentication mode="Forms">
            <forms loginUrl="~/Account/Login.aspx" timeout="2880"  />
          </authentication>
          <authorization/>
          <authorization>
            <deny users="?"/>
          </authorization>

      Ya que el tag

      <authorization>

      se encuentra duplicado.

      En mi caso, duplicando el tag

      <authorization>

      obtengo el mismo error (aunque se muestra en inglés es el mismo).

      Config section 'system.web/authorization' already defined. Sections must only appear once per config file. See the help topic <location> for exceptions

      Lo te recomiendo es que busques el tag que vas a agregar al archivo de configuración y lo reemplaces en lugar de agregarlo, un tema importante, ahora que veo el mensaje de error, es que al utilizar el tag

      <location>

      pueden duplicarse algunos tags, ya que son configuraciones particulares que se aplican a carpetas específicas del sitio

      Espero que sea de ayuda y suerte

  14. Sergio dice:

    Estoy usando la autenticación por formularios y me pasa que la página de login no me carga la masterpage y por lo tanto no me muestra estilos css. Será por algo que estoy omitiendo o siempre pasa así?

    Mi web.config tiene la siguiente configuración:

    y cuando me manda a Default.aspx no me aparecen los estilos. Default.aspx tiene configurado:
    MasterPageFile=”~/MasterPage.master”
    para que me cargue los estilos y otras funciones definidas en MasterPage.master

    • Sergio dice:

      No me salió el codigo del archivo web.config… a ver si ahora sale..

    • Dario Krapp dice:

      Parece ser un tema de permisos.

      Por favor probá ingresar a la aplicacion proporcionando un usuario y clave válidos y luego (sin salir de la aplicacion, o sea sin hacer un sign out) ingresá a la página default.aspx. En este caso los estilos y scripts deberían funcionar.

      Si lo que sucede es esto que describo, te comento que al utilizarse autenticación por formularios todos archivos cumplen las reglas de autorización definidas en el web.config, incluidos los archivos css, scripts, etc.En este caso deberías hacer un ajuste en el web.config para que todo usuario pueda acceder y utilizar estos archivos.

      Por ejemplo, si los estilos se encuentran en la carpeta Styles y se desea que tanto usuarios autenticados o no autenticados puedan descargar (y consecuentemente ver) los estilos, deberías darle autorizacion a esa carpeta a todos los usuarios que ingresen al sitio, una opcion es incluir las siguientes lineas en el web.config (dentro del tag “configuration”):

      <location path="Styles">
          <system.web>
            <authorization>
              <allow users="*" />
            </authorization>
          </system.web>
        </location>

      De esta forma estás especificando que cualquier usuario (autenticado o no) pueda descargar los archivos dentro de la carpeta “Styles”. No hay que olvidarse que con estos tags estamos manejando permisos y esta tarea implica responsabilidad, sobre todo dando permisos a cualquier usuario a que descargue archivos del sitio, pero en el caso de css’s o scripts seguramente no va a haber problemas.

      Suerte!

  15. Mario dice:

    hola buenas tardes, estoy desarrollando una aplicacion, pero me encontre con un problema, que por ejemplo me logueo con un usuario A, pero si en esa maquina no cierro la session y ese mismo usuario A entra a otra maquina lo deja entrar, pero ya con una session ya inicializada, como le puedo hacer para cerrar la session anterior o al menos que me diga el propio sistema que ya hay una sesion abierta con ese usuario y que me diga si puedo cerrarla, y si le digo cerrar que me cierre esa sesion y entrar con la k estoy intentando abrir, de lo contrario que no me deje abrir otra sesion.

    espero que me puedan ayudar, gracias

    saludos

  16. Jesus dice:

    Hola, tengo una consulta.

    La autentificación me funciona perfectamente, pero me carga inclusive si mi página de inicio esta configurada para ser un recurso “publico” es decir que la página de inicio puede ser vista sin necesidad de autentificarse.

    Ejemplo:

    Tengo mi ruta: http://www.midominio.com/inicio.aspx y me carga bien, no me pide autentificarme. Oviamente inicio.aspx es mi página de inicio, valga la redundancia.
    Pero si pongo http://www.midominio.com, me pide la autentificación.

    Que puedo hacer en este caso?

    • Hola, Jesus.
      Te hago una consulta: cuál es tu página por defecto? Si no es “inicio.aspx” podés cambiarlo desde el IIS o, en caso que sea un IIS 7.0 o mayor, podés cambiarlo desde el web.config en la siguiente sección:

      <system.webServer>
        <defaultDocument>
          <files>
            <clear />
            <add value="inicio.aspx" />
          </files>
        </defaultDocument>
      </system.webServer>

      En esta página se explica con más detalle cómo cambiar esta configuración: Default Document.
      Suerte!

  17. Leonardo dice:

    Hola, tengo una aplicación hecha con funciona muy bien la primera vez, pero si el usuario cierra la pestaña del explorador e ingresa otro usuario no vuelve a pedir la contraseña. Si cierra el explorador de forma completa si vuelve a pedir una contraseña.
    A que de debe o como lo puedo solucionar? gracias.

    • Hola, Leonardo.
      El tema es que cuando te logeás en un sitio web las credenciales se guardan por instancia del navegador, por eso no te las vuelve a pedir hasta cerrar el browser por completo (a no ser que implementes una opción de logout).
      Saludos.

      • Leonardo dice:

        Hola Gustavo, efectivamente tenemos incorporado la opción logout, pero los estudiantes solo cierran la pestaña y no el explorador, por lo tanto cuando otro estudiante utiliza el equipo accede al login anterior.
        Existe alguna forma de controlar eso o sería mejor buscar otra alternativa para controlar el acceso a paginas restringidas?

        Gracias.

  18. Veronica dice:

    Hola Tengo un inconveniente tengo un formulario de autentificación que verifica por directorio activo se llama Default.aspx, la web.config esta:

    cuando ingreso el usuario y voy a entrar a principal que es donde esta el contenido me sale

    http://localhost/Intranet/Default.aspx?ReturnUrl=

    se supone que ya ingrese el usuario un contraseña correcta, como lo puedo configurar.

  19. scrilexx xiom dice:

    Hola Dario, gracias por la guia es excelente.
    Te hago una consulta supongamos que tengo una base de datos de clientes en sql server
    quiero hacer una pagina de logueo y que el cliente se loguee con su id de cliente y que cdo ingrese vea su deuda, me podrias ayudar como lo tengo q hacer me das algunos tips?

    • Dario Krapp dice:

      Hola, buenos días

      Por un lado deberías implementar autenticación por formularios tal como se explica en el artículo, una vez que tengas la autenticacion por formularios funcionando y puedas loguearte lo que te va a interesar es poder saber qué usuario se encuentra logueado.

      Por el contexto imagino que necesitás hacer esto desde una página .aspx y lo bueno es que la tarea no es muy compleja, ya que la clase System.Web.UI.Page cuenta con la siguiente propiedad:

        public class Page : TemplateControl, IHttpHandler
          {
      
      	....
      	.......
      	............
              //
              // Summary:
              //     Gets information about the user making the page request.
              //
              // Returns:
              //     An System.Security.Principal.IPrincipal that represents the user making the
              //     page request.
              [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
              [Browsable(false)]
              public IPrincipal User { get; }
      

      Por lo que que podrías hacer por ejemplo lo siguiente:

              protected void Page_Load(object sender, EventArgs e)
              {
                  if (this.User.Identity.IsAuthenticated)
                  {
                      string username = this.User.Identity.Name;
      

      Para obtener quién es el usuario logueado y desde ahí en más obtener su id y luego (según lo que me comentás) buscar su deuda en una tabla relacionada con el id de usuario y finalmente mostrarla en la página, o sea:

              protected void Page_Load(object sender, EventArgs e)
              {
                  if (this.User.Identity.IsAuthenticated)
                  {
                      string username = this.User.Identity.Name;
      
                      int uid = ObtenerIdDesdeBD(username); 
      
                      decimal deuda = ObtenerDeudaDesdeDB(uid);
      
                      MostrarDeudaPantalla(deuda); 
      

      Obviamente este es un ejemplo solo para explicar la metodología, en un caso real seguramente guardarás el Id de usuario para reutilizarlo. Por otra parte deberías decidir que hacer si el usuario no se encuentra logueado, para eso puede servirte la sección de “Autorización” que se comenta en el articulo.

      Espero que haya sido de ayuda
      Slds

  20. Gabriel dice:

    Amigo todo excelente, solo que tu estableciste manualmente los usuarios autentificados, y que si se tiene que hacer una consulta dentro de una base de datos SQL server?? un cordial saludo.

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.