Archivo de Octubre 2009


Establecer modo de compatibilidad en Internet Explorer 8

Miércoles, 28 Oct, 2009 @ 14:50 | Por Gustavo Cantero (The Wolf) | IE 8

Habrán notado que el Internet Explorer 8 posee, al navegar en la mayoría de los sitios, un botón a la derecha de la dirección para emular la visualización de las páginas como si estuviéramos viéndolas en un Internet Explorer 7:

Modo de compatibilidad en IE8

Bueno, esta opción no es la única que posee el Internet Explorer para decidir como visualizar el contenido de las páginas, posee una característica llamada “Compatibility Mode” (modo de compatibilidad) gracias a la cual nosotros, los desarrolladores, podemos decirle a través de la etiqueta META de nuestras páginas, o agregándole un valor al encabezado de http, cómo queremos que “dibuje” la misma. En caso de que se establezcan ambos y que el valor del primero difiera del establecido en el encabezado http, se utilizará el de la etiqueta.

El navegador elige el modo de visualización basado en el modo de compatibilidad especificado y en el DOCTYPE de la página.

Tanto en el encabezado de http como en la etiqueta META hay que agregar el ítem “X-UA-Compatible” con el valor de la compatibilidad deseado. Por ejemplo, en la siguiente línea muestro cómo hacer para que la una página se visualice como en Internet Explorer 7, dependiendo del DOCTYPE:

<meta http-equiv="X-UA-Compatible" content="IE=IE7" />

A continuación les dejo una lista de los posibles valores de compatibilidad

Valor Nombre Descripción
IE=8 Modo estándar IE8 Visualización en modo de Internet Explorer 8
IE=7 Modo estándar IE7 Visualización en modo de Internet Explorer 7
IE=5 Modo quirks Visualización en modo de Internet Explorer 5, comúnmente llamado “quirks mode”
IE=EmulateIE8 Modo de emulación IE8 Si la página tiene un DOCTYPE lo utiliza en modo de IE8, sino usa el modo quirk (IE5)
IE=EmulateIE7 Modo de emulación IE7 Si la página tiene un DOCTYPE lo utiliza en modo de IE7, sino usa el modo quirk (IE5)
IE=Edge Último modo disponible La página se visualiza en el modo más alto disponible por el navegador. Esta opción es utilizada, generalmente, para propósito de pruebas.
VN:F [1.7.3_972]
Rating: 8.7/10 (3 votes cast)

Autenticación por formularios en ASP.NET

Lunes, 19 Oct, 2009 @ 10:59 | Por Dario Krapp | AJAX, ASP.NET

Prólogo e inicios

En algunas tecnologías web antiguas, como por ejemplo ASP (en el caso de Microsoft) la programación de la autenticación de los usuarios quedaba en manos de los programadores. A pesar de que no es una tarea extremadamente compleja, demandaba tiempo de desarrollo, pruebas y correcciones por cada sitio que se desarrollaba y aunque las técnicas utilizadas para esta funcionalidad se encontraban informalmente estandarizadas, siempre podían existir diferencias en las implementaciones (quien haya caído en la suerte de tener que modificar una aplicación legada, posiblemente sabrá a que nos referimos ), lo que influía en los tiempos y costos del desarrollo y si lo analizamos parecería tener poco sentido el gasto de esfuerzos de desarrollo en una tarea que es tan repetitiva. Quizás esa sea una de las causas por las que ASP.NET provee un sistema de autenticación ya incluido, lo que implica código, desarrollado, testeado, mantenido y listo para usar. En este artículo nos adentraremos en la autenticación por formularios desde sus comienzos en las primeras versiones de ASP.NET hasta la versión 3.5 (y diría que también hasta la versión 4.0, ya que hasta el momento no se han introducido modificaciones sobre estos ítems en la versión 4.0 y según parece, tampoco hay intenciones de hacerlo) y comentaremos algunos otros temas relacionados.

Para empezar diremos que la autenticación es el acto de confirmar que algo o alguien es quien dice ser y autorización es el acto de dar permisos (o denegárselos) a algo o alguien (ya autenticado) sobre un recurso, diremos además que algo o alguien es anónimo si no ha sido autenticado, que la acción de loguearse (login) consta de informar las credenciales a fin de poder autenticarse y la acción de desautenticarse (logout), si me permiten el término aunque no suene de lo mejor, consta de volver a un usuario autenticado al estado de anónimo.

En ASP.NET el modo de autenticación por formularios es aplicable para aplicaciones web que requieren autenticación, siempre que la misma no sea autenticación de Windows, para tales casos ASP.NET ofrecerá la opción de establecer el modo de autenticación Windows, pero ese es otro tema.

ASP.NET a través del modo de autenticación por formularios nos brindará mecanismos y funcionalidades que nos ayudarán a realizar ambas tareas: autenticación y autorización.

Para que el modo de autenticación por formularios funcione, solo debemos activarlo y la forma es simplemente ajustar la propiedad mode del tag authentication (del archivo web.config) en Forms, tal como se muestra a continuación:

<authentication mode="Forms">

El modo de autenticación por formularios creará una cookie con la información básica del usuario (obviamente encriptada), la cual será enviada por el browser en cada solicitud y el Servidor analizará la información de esta cookie para hacer los chequeos de autenticación y autorización necesarios. Este modo de funcionamiento es necesario debido a que en un entorno web las conexiones entre el cliente y el servidor se establecen y se cortan en cada solicitud. Por defecto la cookie tomará el nombre “.ASPXAUTH”.

En el siguiente esquema pueden observarse paso a paso las verificaciones de autenticación y autorización que realizará ASP.NET cuando una solicitud es procesada y se está utilizando autenticación por formularios:


Autenticación por formularios

El proceso graficado será realizado automáticamente por ASP.NET con simple hecho de haber establecido el atributo mode como Forms.
En nuestros ejemplos (que los estaremos realizando sobre Visual Studio 2008 SP1) utilizaremos una aplicación web que inicialmente contendrá la página Default.aspx, que es creada automáticamente junto con el proyecto.

Estructura del proyecto

Si en el ejemplo, luego de haber establecido el modo de autenticación por formularios, intentamos acceder a la página Default.aspx, notaremos que podremos hacerlo sin problemas, pero no debemos preocuparnos, este comportamiento se debe a que aún no hemos definido las reglas de acceso, por ahora cualquier usuario podrá acceder a cualquier recurso del sitio.

Para evitar que esto suceda, deberemos configurar las reglas de acceso. Por ahora, para simplificar lo haremos agregando las siguientes líneas dentro de la sección system.web del archivo web.config:

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

Luego veremos en detalle las opciones disponibles para esta sección de la configuración, pero la sintaxis que utilizamos es bastante intuitiva, estaremos indicando que deberá negársele el acceso a cualquier recurso del sitio a los usuarios anónimos (identificados con el signo “?”, recordemos que un usuario anónimo es aquel que no se ha autenticado).

Si luego de esta modificación intentamos acceder nuevamente a Default.aspx (que es un recurso del sitio) veremos que somos automáticamente redireccionados a la página login.aspx, obteniendo un resultado similar al siguiente en la barra de direcciones del explorador:

http://localhost:6931/login.aspx?ReturnUrl….

Se obtendrá un error dado que la página login.aspx no existe, pero ese detalle mínimo pierde importancia ya que como podemos ver, el mecanismo está funcionando.

Lo que está haciendo ASP.NET es verificar la cookie, y al no encontrarla nos ha enviado a un formulario para que ingresemos nuestras credenciales y podamos autenticarnos.

La pagina login.aspx es la página de redirección que utiliza ASP.NET por defecto, pero es posible modificar este comportamiento definiendo un tag denominado forms dentro del tag authentication en el web.config como se muestra a continuación:

<authentication mode="Forms">
      <forms loginUrl="ingreso1.aspx"></forms>
</authentication>

Y no habrá quien se sorprenda de que luego de esta última modificación, la redirección sea a:

http://localhost:6931/ingreso1.aspx?ReturnUrl…….

Existen varias opciones aplicables al tag forms, algunas de ellas, además de loginUrl son:

  • name: Nombre de la cookie (el valor por defecto es .ASPXAUTH).
  • defaultUrl: pagina de redirección si la autenticación fue satisfactoria y el usuario había ingresado originalmente a la página de logueo (login.aspx por defecto).
  • timeout: tiempo de vida de la cookie.
  • slidingExpiration: si es verdadero, el tiempo de vida de la cookie se reiniciará cada vez que la página es reenviada.
  • cookieless: permite definir si se utilizarán cookies para mantener la información del usuario.
  • requireSSL: En verdadero indicará que el browser enviará la cookie al solo si la conexión es segura (SSL) en caso contrario de no contarse con una conexión segura, no funcionará la autenticación por formulario.
  • domain: Permitirá definir en qué dominio la cookie es válida.
    path: Permitirá definir el path de la cookie.

Para continuar con el ejemplo agregaremos la página ingreso1.aspx que será desde ahora en más nuestra página donde el usuario deberá ingresar sus credenciales para autenticarse (login).

Con estas simples modificaciones en el archivo de configuración hemos conseguido dar un primer paso a incorporarle a nuestro sitio la autenticación por formularios. Ahora que hemos conseguido que nadie pueda ingresar, debemos permitir que algunos usuarios si puedan hacerlo, y en particular aquellos a los que deseemos permitirles el ingreso. En este punto encontraremos dos opciones, una de ellas es encargarnos de autenticar al usuario por nuestra cuenta, lo que implica hacer el chequeo manualmente vía código y la otra será una opción automática con algunas particularidades.

Para el primer caso tomará importancia una clase llamada FormsAuthentication. Esta clase (como su nombre indica) nos ayudará a realizar todas las funcionalidades relacionadas con la autenticación por formularios programáticamente, como por ejemplo autenticar a un usuario y redireccionarlo a la pagina que el mismo había solicitado cuando se le denegó el acceso.

Para realizar la autenticación vía código con la ayuda de la clase FormsAuthentication escribiremos lo siguiente:

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

Hemos asumido que poseemos los cuadros de texto, Usuario, Clave y el botón Login, donde hemos utilizado el evento Click del mismo para agregar el código que puede verse en las líneas superiores. De más está decir que no hemos mencionado a los validadores con el único objetivo de simplificar el ejemplo.

Si probamos el ejemplo intentando ingresar a la página Default.aspx seremos redireccionados a la página Ingreso1.aspx donde deberemos ingresar nuestras credenciales, tal como se muestra a continuación:


Autenticación

Solo podremos acceder a Default.aspx si utilizamos como usuario a “Juan” y como clave a “clavedejuan”.

En el código que terminamos de agregar podemos ver también que nos estamos valiendo del método RedirectFromLoginPage de la clase FormsAuthentication para indicar la autenticación del usuario y la redirección a la página solicitada originalmente por el mismo.

Por otra parte podríamos incluir en la página Default.aspx un botón con la siguiente funcionalidad:

protected void LogOut_Click(object sender, EventArgs e)
        {
            FormsAuthentication.SignOut();
            FormsAuthentication.RedirectToLoginPage();
        }

Al presionarlo se ha utilizado una vez más la clase FormsAuthentication para desautenticar al usuario y reenviarlo a la página de ingreso nuevamente.

Con estas operaciones hemos conseguido que un usuario pueda realizar las operaciones de autenticación, en tal caso será simple reemplazar la sentencia Usuario.Text == “Juan” && Clave.Text == “clavedejuan” que utilizamos en el ejemplo por la llamada a un método que acceda al repositorio que más deseemos para efectuar la validación de las credenciales del usuario.

Si se observa la clase FormsAuthentication se notará que existe un método llamado Authenticate que toma por parámetros un nombre de usuario y una clave y devuelve un valor booleano, podríamos preguntarnos si este método será capaz de realizar la autenticación por nosotros, esta es la segunda opción que habíamos mencionado en algunos párrafos previos y para probar como funciona, podremos modificar el código anterior de la siguiente forma:

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

Si ahora intentamos ingresar nuevamente, ya no importa que usuario y clave utilicemos, no podremos hacerlo, lo cual es un resultado bastante esperable, si consideramos le hemos delegado el control de la autenticación ASP.NET pero aún no le hemos indicado quienes serán los usuarios válidos de la aplicación. Si se desea utilizar esta opción automática debe considerarse la particularidad de que los usuarios deberán definirse en el propio archivo de configuración web.config, como se muestra en el siguiente ejemplo:

<authentication mode="Forms">
  <forms loginUrl="ingreso1.aspx" >
    <credentials passwordFormat="Clear">
      <user name ="Pepe" password ="clavedepepe"/>
      <user name ="Pedro" password ="clavedepedro"/>
    </credentials>
  </forms>
</authentication>

Luego de agregar estos valores veremos que es posible ingresar con ambos usuarios. El atributo passwordFormat del tag credentials admitirá además de la opción Clear (claves en formato limpio, o sea en texto legible para quien abra el archivo web.config) las opciones MD5 y SHA1 que permitirán utilizar el hash de la clave del usuario utilizando los algoritmos MD5 o SHA1. Claro está que en tal caso deberemos crear un mecanismo capaz de establecer dichos valores, lo bueno es que para obtener los valores hash en ambos formatos la clase FormsAuthentication ofrecerá el método HashPasswordForStoringInConfigFile que permitirá tomar una clave limpia y obtener el valor de hash correspondiente en el formato deseado. En el ejemplo anterior, si deseamos utilizar por ejemplo MD5 deberemos efectuar las siguientes modificaciones:

<authentication mode="Forms">
  <forms loginUrl="ingreso1.aspx">
    <credentials passwordFormat="MD5">
      <user name="Pepe" password="957995AA67183A4D2A91F7DE3EB9A692"/>
      <user name="Pedro" password="B447CA7CBA96E91D68D43C5867522BF0"/>
    </credentials>
  </forms>
</authentication>

Donde los valores de hash se han obtenido efectuando las siguientes llamadas:

string HashedPasswordPepe = FormsAuthentication.HashPasswordForStoringInConfigFile("clavedepepe " , "MD5");

y

string HashedPasswordJuan = FormsAuthentication.HashPasswordForStoringInConfigFile("clavedejuan " , "MD5");

Si bien todo esto funciona, creo que es inevitable pensar que se podría dar un próximo paso, ya que al fin de cuentas con este esquema que terminamos de ver, si bien ASP.NET y la clase FormsAuthentication nos han ayudado a controlar la autenticación y la autorización, la funcionalidad de la autenticación debimos codificarla, y cuando utilizamos la autenticación automática con el método Authenticate debimos definir a los usuarios en el archivo web.config. No sería nada malo que ASP.NET pudiese combinar ambas opciones y permitirnos efectuar la autenticación automáticamente sobre cualquier repositorio que deseáramos utilizar.

VN:F [1.7.3_972]
Rating: 8.6/10 (8 votes cast)

Introducción a Task Parallel Library (TPL)

Jueves, 15 Oct, 2009 @ 15:36 | Por Gustavo Cantero (The Wolf) | .NET Framework

Tal como fue expresado por Gordon Moore, cofundador de Intel, en 1965 en la conocida “Ley de Moore”, la cantidad de transistores que poseen las computadoras se duplicaría aproximadamente cada 18 meses (un año y medio), y esta tendencia continuaría durante las siguientes dos décadas. Unos diez años después corrigió su ley diciendo que la cantidad de transistores se duplicará cada 24 meses (2 años). Esta ley fue cumplida durante mucho tiempo (mucho más del que él pensaba al momento de formularla) generando una carrera en la generación de procesadores cada vez más potentes, hasta hace unos pocos años. Al llegar al límite (o muy cerca) del tamaño que se le puede dar a éstos transistores (por lo menos utilizando las técnicas actuales) se comenzaron a generar nuevos procesadores con varios núcleos, o sea, varios procesadores en una misma “pastilla”. Esto dio origen a los primeros procesadores Multi-Core, los cuales hoy en día son muy comunes en los equipos de escritorio y notebooks.

Hasta aquí todo parece ser bueno, pero para los desarrolladores no lo es tanto, ya que las aplicaciones que venimos desarrollando son, por lo general, creadas para ejecutarse en un único hilo (thread), y para poder utilizar el poder de estos nuevos procesadores hay que cambiar la forma de programar. Supongamos que tenemos una aplicación que calcula los números primos existentes entre el 1 y 1.000.000.000, seguramente esta tarea llevaría bastante tiempo, y aunque lo ejecutemos en una máquina con ocho núcleos (o, por ejemplo, cuatros procesadores con doble núcleo) veremos que sólo uno de los procesadores trabajará al 100%, mientras que el resto no realizará ninguna tarea. Para mejorar la performance de esta aplicación en esta máquina lo optimo sería distribuir la tarea en ocho threads para que cada uno se ejecute en un procesador distinto y reducir de esta manera el tiempo en conseguir el resultado.

Crear estos threads y distribuir la carga de trabajo hace que nuestro código sea más largo, difícil de leer, propenso a errores, y el crear ocho threads (como comentamos antes) no siempre es lo mejor, ya que esto depende de la carga de los procesadores y de la cantidad de éstos que dispongamos en cada máquina donde se vaya a ejecutar nuestra aplicación. Para facilitar estas tareas aparece la .NET Task Parallel Library, o como se la conoce, la TPL.

Task Parallel Library

Esta librería fue creada en un esfuerzo en conjunto del Microsoft® Research, el equipo del Parallel Computing Platform y el equipo del Microsoft® Common Language Runtime (CLR). La misma se encuentra incluida en la beta 1 del .NET Framework 4.0, pero puede utilizarse su versión CTP para .NET Framework 3.5 descargándola de la siguiente página: Microsoft Parallel Extensions to .NET Framework 3.5, June 2008 Community Technology Preview.

Cabe mencionar que en .NET Framework 4.0 hay muchas novedades sobre paralelismo, por ejemplo, está Parallel LINQ (también conocido como PLINQ), una librería para utilizar LINQ distribuyendo su carga en los procesadores disponibles, Parallel Pattern Library (o PPL) una librería de patrones utilizados en algoritmos concurrentes, y varias cosas más que exceden el alcance de este artículo.

TPL nos brinda distintas clases y métodos para distribuir y hacer un balance de carga de las tareas que debe realizar nuestra aplicación sobre los distintos procesadores que tengamos disponibles en la máquina en tiempo de ejecución. Por ejemplo, supongamos que tenemos una máquina con un procesador de doble núcleo y nuestra aplicación debe realizar tres tareas, el TPL ejecutará las dos primeras, una en cada núcleo, y al concluir cualquiera de éstas comenzará a ejecutar la tercera tarea en el núcleo disponible. Si esta misma aplicación la corremos en una máquina que posea más de dos núcleos ejecutará las tres tareas al mismo tiempo.

Hay que mencionar que la creación, administración y sincronización de estas tareas y threads por parte del TPL generan una carga extra de trabajo, pero ésta es muy pequeña y la ganancia al utilizar todos los procesadores de la máquina es enorme.

En .NET Framework 4.0 esta librería está incluida en el archivo mscorlib.dll, con lo cual podemos utilizarla sin necesidad de agregar librerías, pero si queremos usarla desde una aplicación desarrollada con .NET 3.5, además de bajar e instalar el CTP desde la dirección mostrada anteriormente, tenemos que referenciar el archivo System.Threading.dll desde nuestro proyecto.

La librería posee complejos algoritmos para la distribución dinámica de la carga entre los procesadores, pero esto sólo representa una posible ejecución en paralelo, ya que en una máquina con un único procesador las iteraciones se ejecutarán de manera secuencial en el mismo thread. Sin embargo hay que tener en cuenta que cuando utilizamos esta librería en una máquina multi-core es muy probable que se ejecuten varias acciones al mismo tiempo, por lo tanto es necesario tratar de evitar el uso compartido de variables entre éstas ya que podrían solaparse, pero para el caso en que esto sea necesario, más adelante mostraré como se puede hacer de manera segura.

VN:F [1.7.3_972]
Rating: 7.5/10 (2 votes cast)