Nuevo catálogo de campusMVP: más cursos, más variedad de precios y también cursos gratuitos

Este verano, abrimos por vacacionesPues nada, hoy toca cuña publicitaria, pero creo que os va a interesar 🙂


Y es que hoy hemos lanzado nuestro nuevo catálogo de cursos de campusMVP. Y esto es sólo el principio, pues a lo largo del verano lo ampliaremos y además iremos lanzando muchas cosas nuevas que estamos seguros de que te van a encantar.


Hemos hecho caso a todo lo que nos han dicho los alumnos últimamente y encontrarás muchas novedades: cursos más baratos, más tiempo para hacerlos, descuentos para desempleados, posibilidad de pagar todos los cursos con tarjeta y cursos gratuitos para que pruebes como se siente un alumno de campusMVP.


Cuantos más cursos elijas más descuentos puedes obtener. Y también tenemos soluciones específicas para las empresas. Nunca fue tan fácil construirte una formación a la carta.


Consulta nuestra nueva oferta formativa y aprovecha el verano para aprender. Échale un vistazo también a la nueva colección de cursos ‘Al día en un día’, que te permitirá controlar los fundamentos de las últimas tecnologías en unas horas de formación rápida, y a un precio muy asequible.


902 876 475Finalmente lanzamos una nueva convocatoria de nuestros cursos de formación oficial Microsoft. Comienzan el día 15 de Julio y tenemos varias novedades. A nuestro exitoso curso 70-536 que hemos reformado y mejorado, se le unen la nueva certificación en desarrollo web para Visual Studio 2008, así como un curso oficial de desarrollo de aplicaciones seguras y el curso oficial de Transact SQL para SQL Server 2005-2008.


No te quedes sin plaza y apúntate cuanto antes. ¡Comenzamos el día 15!.


Apúntate a nuestro boletín para estar al tanto de todas las novedades y recibir trucos de programación, noticias y nuestras clásicas secciones de «Gambadas» y «Frikadas», jeje


Pues nada, ahí queda eso 🙂

Acrobat Professional y firma digital de documentos en Windows Vista: sus problemas y cómo resolverlos

Como es sabido, desde hace ya bastantes años (1.999) la firma digital de documentos tiene validez legal en España. Además se puede utilizar en multitud de trámites con el Gobierno y las Administraciones Regionales y Locales. Por ello fui de los que se dio prisa en sacarle partido y solicitarla para poder firmar contratos, correos electrónicos, etc… Y no sólo yo, sino con el certificado digital de la empresa también.


Bien, el caso es que una de las aplicaciones de firma digital más comunes y utilizadas en el mundo es Adobe Acrobat Professional. Lo que se hace es pasar el documento a PDF y luego con esta herramienta estampar una firma digital en el documento usando el certificado digital correspondiente. A partir de ese momento cualquier mínima modificación del mismo anula la validez de la firma y además se ofrece el «no repudio», es decir, atestigua de forma fehaciente que el que firma el documento es quien dice ser.


Yo dispongo de Acrobat 7.0, que no es la última versión sino una más antigua pero que para lo que yo lo uso me sobra. Cuando lo instalas bajo Windows Vista (o actualizas tu XP a Vista) resulta que las firmas digitales dejan de funcionar. Cuando vas a firmar cualquier documento ya de entrada no te deja elegir todos los certificados, pero además es que cuando elijes uno de los que sí te deja (aunque sea para probar) obtienes un error que dice:



«Creation of this signature could not be completed.
Certificate parsing error:

x.509 parsing error

Error encounted while BER decoding: «


¿Qué diablos es esto?. Además por más que busques en Internet no hay apenas información y en la web de soporte de Adobe menos (desde mi punto de vista son muy malos en este y otros aspectos).


Bueno, pues os voy a dar la solución que he encontrado yo…


Todo el problema viene porque no es capaz de reconocer y leer correctamente un certificado especial que introduce Windows Vista para facilitar las comunicaciones Peer To Peer en Vista (para productos como el Área de Encuentro y otros). El último parche para la versión más reciente del producto (la 8.0 y pico) sí soluciona el problema,pero en el resto de los casos hay que buscarse la vida.


La solución pasa por retirar ese certificado especial. Para ello vete al menú Avanzadas·Configuración de seguridad y en el primer nodo «IDs digitales» verás todos los certificados disponibles:



El certificado «chungo» que debes retirar es el que tiene fecha de caducidad en el año 3008 🙂


Así que selecciónalo y pulsa el botón «ELiminar ID». A partir de ese momento ya te volverá a funcionar de manera normal la firma digital.


Ojo, si crees que puedes necesitar ese certificado en el futuro debes exportarlo antes de borrarlo. Al hacerlo asegúrate de que exportas tanto la clave pública como la privada. Guárdalo en un sitio a buen recauso y si vuelves a necesitarlo sólo tienes que volver a importarlo.


Espero que esto le pueda sacar a alguien de un apuro alguna vez 🙂

Clon de RunAs.exe (II): petición segura de contraseña

En mi anterior post hablaba de cómo construir un programa «clon» de la utilidad de línea de comandos Windows RunAs. En esta primera parte vimos cómo se lanzaba un proceso suplantando a un usuario, que era el objetivo principal de la aplicación, si bien es la parte más fácil.


La tarea que nos quedó pendiente de ver es la más complicada y consiste en solicitar al usuario la clave de manera segura, sin que llegue a estar almacenada en claro en la memoria siquiera. Para ello usamos la clase SecureString, que apareció para estos menesteres en la versión 2.0 del framework.


Sin más vueltas vamos a ver directamente cómo se solicita dicha clave y pasamos a explicar los puntos de interés:

        private static SecureString PideClave(string nomUsuario)
{
Console.WriteLine(«Escriba la contraseña para {0}:», nomUsuario);

int top, left;
ConsoleKeyInfo cki;
SecureString clave = new SecureString();

top = Console.CursorTop;
left = Console.CursorLeft;

bool ModoEntrada = true;
while (ModoEntrada)
{
cki = Console.ReadKey(true);

switch(cki.Key)
{
//Si se pulsa ESC salimos del bucle
case ConsoleKey.Escape:
ModoEntrada = false;
clave = null; //devolvemos un null para indicar que el programa debe terminar
break;

//Con ENTER terminamos la entrada de datos
case ConsoleKey.Enter:
ModoEntrada = false;
break;

//Si se pulsa la tecla de borrado hacia atrás hay que «currarse» el eliminar el caracter
//y que se vea en la pantalla eso
case ConsoleKey.Backspace:
if (clave.Length > 0)
{
Console.SetCursorPosition(left + clave.Length 1, top);
Console.Write(» «);
Console.SetCursorPosition(left + clave.Length 1, top);
clave.RemoveAt(clave.Length 1);
}
break;

//Cualquier otra tecla
default:
if (Char.IsLetterOrDigit(cki.KeyChar) || cki.KeyChar == ‘_’)
{
clave.AppendChar(cki.KeyChar);
//Se sustituye por un asterisco
Console.SetCursorPosition(left + clave.Length 1, top);
Console.Write(‘*‘);
}
break;
}
}
Console.Write(«n»);
return clave;
}


Básicamente lo que se hace es ir solicitando las letras de la clave una a una, capturando las pulsaciones de las teclas con el método ReadKey de la clase Console. Este método toma un parámetro opcional que indica si se debe mostrar el caracter pulsado por pantalla o no. En este caso le indicamos que debe interceptar la pulsación de la tecla y no mostrarla por pantalla (valor true en el parámetro del método). Lo que hacemos posteriormente es escribir un asterisco. De este modo damos información visual sobre cuántos caracteres se han introducido, pero no los mostramos ni permitimos que se almacenen en lado alguno, sino que los metemos dentro de la cadena segura con su método AppendChar.


También capturamos algunas teclas especiales que se pueden pulsar:




  • ESC: con esto devolvemos un nulo que se comprueba en el código llamante parando la ejecución del programa.


  • ENTER: finalizamos la introducción de datos dando por válida la contraseña introducida hasta el momento.


  • BACKSPACE: la tecla de borrado (con la flechita a la izquierda), que sirve para corregir el último caracter.

Listo. con esto pedimos la clave al usuario sin comprometer la seguridad haciéndola pasar por una cadena normal. Éstas son objetos inmutables que permanecen en memoeria mientras no las reclame el recolector de basura y aunque las «sobrescribamos» (es un decir, por que lo que conseguiríamos es sólo una nueva cadena, ya que no se destruyen al asignarle otro valor a la misma variable, como se comenta en ese post antiguo que referencio).


Exactamente el mismo principio se podría aplicar para pedir de manera segura una clave en una aplicación Windows (capturando letra a letra y sin dejar que éstas se reflejen luego en la interfaz de usuario o en alguna cadena).


También os dejo, como prometí, el código completo del programa RunAsClon (20 KB) para que el que quiera le pueda echar un vistazo. He usado regiones condicionales para laznar el programa de manera cómoda para depurar mientras estamos en modo de desarrollo (debug), pero es lo único a mayores que tiene el código. Lo he hecho con Visual Studio 2008 pero funcionará perfectamente con Visual Studio 2005 también si importas el .cs. He incluido el resultado de la compilación tanto en depuración como en «release» por si alguien lo quiere utilizar directamente sin tener que compilarlo.


Si alguien quiere crear su propio programa RunAs que se ejecute sin pedir la clave al usuario, sino incluyéndola como parte de la lñinea de comandos (no recomendable pero útil en muchos casos) puede tocar ligeramente este código para conseguirlo sin problema.


¡Espero qué te resulte útil!

Clon de RunAs.exe: cómo suplantar a un usuario con .NET 2.0

Esta es la primera parte de una serie de dos. El planteamiento es crear un programa que replique la funcionalidad básica de «RunAs«, la utilidad de línea de comandos que permite ejecutar cualquier programa suplantando a otro usuario. Nuestro particular RunAs se encargará de solicitarnos de forma segura la clave para el usuario indicado y luego lanzará el .exe indicado suplantando al mismo y por lo tanto permitiéndonos hacer una escalada de privilegios o, por el contrario, ejecutar un programa con menos privilegios que el usuario actualmente autenticado en el sistema.


Su uso básico es este:



runas usuario ejecutable.exe


o bien



runas dominiousuario ejecutable.exe


si queremos indicar el dominio también.


En este primer post voy a mostrar lo más sencillo que es lanzar el proceso suplantando a un usuario. Dejaré para el próximo la obtención de la clave del usuario y su almacenamiento seguro y pondré el código completo para descarga.


El código principal del programa es el que muestro a continuación y que ahroa explicaré:


public static void Main(string[] args)
{
if (args.Length != 2)
{
MuestraUso();
return;
}

//Nombre de usuario a suplantar
string usuario = args[0];
string[] partes = usuario.Split(‘\’);

SecureString claveSegura = PideClave(usuario);

//Si no han introducido han pulsado ESC salimos sin hacer nada.
if (claveSegura == null)
return;

//Programa a ejecutar
string programa = args[1];

try
{
ProcessStartInfo psi = new ProcessStartInfo(programa);
psi.UseShellExecute = false;

if (partes.Length == 2)
{
psi.Domain = partes[0];
psi.UserName = partes[1];
}
else
{
psi.UserName = partes[0];
}

psi.Password = claveSegura;

Process.Start(psi);
}
catch (Win32Exception e)
{
Console.WriteLine(«Se ha producido un error ejecutando la aplicación:»);
Console.WriteLine(e.Message);
}


Si no se introducen dos argumentos en la línea de comandos se usa el método MuestraUso que muestra por pantalla la ayuda del programa (no lo voy a poner aquí pues es trivial). Para poder depurar el programa deberemos introducir unos parámetros de ejemplo en la pestaña «Debug» de las propiedades del proyecto:



En el primer parámetro se espera el nombre de usuario, el cual puede estar formado (o no) por dos partes: el dominio y el nombre de usuario separado por una barra inclinada «», por lo que lo separamos para manejarlos indpendientemente.


El método PideClave, el más interesante de todo el código, se encarga de solicitar la clave al usuario de forma segura (lo veremos en el próximo post).


Usamos la clase ProcessStartInfo, aparecida en .NET 2.0, para lanzar el proceso indicado. Como vemos el código es directo excepto por dos o tres puntos interesantes:



1.- Establecemos la propiedad UseShellExecute a false. Esta propiedad sirve para especificar si se usará el Shell de Windows para lanzar la nueva aplicación o si por el contrario se lanzará directamente un proceso. La principal diferencia entre una u otra opción es que si esta propiedad es false podremos redirigir los flujos de consola (entrada, salida y errores) a voluntad. Además sólo nos permitirá lanzar ejecutables, que es el propósito de este programa. Si usásemos el valor true se podrían lanzar también los ejecutable a partir de un archivo asociado con éstos. Así, si pusiésemos «miDocumento.docx» se ejecutaría Microsoft Word, pero en nuestro caso tendríamos que poner el ejecutable siempre (lo que es más adecuado para el propósito de este programa). Todos los detalles en la página de MSDN para UseShellExecute.


2.- Sólo es posible asignar la clave en la propiedad PassWord usando una cadena segura, es decir, una clase SecureString, también aparecida con .NET 2.0. Más en el próximo.


3.- El método Start de la clase Process se usa para lanzar el proceso a partir de la información almacenada en la clase ProcessStartInfo.


El próximo día comentaré lo que es para mi más interesante de todo este programa: cómo pedir al usuario que introduzca su contraseña por consola de una manera segura, sin almacenarla nunca en memoria y usando la clase SecureString. También dejaré entonces el código de ejemplo completo.


¡Hasta pronto!

GridView de ASP.NET a fondo: no te lo pierdas

El próximo día 1 de Julio tengo el gusto de participar como ponente en este interesante evento on-line de SecondNUG, el grupo de usuarios de .NET en Español que cada vez está teniendo más tirón:




En este evento Luis Miguel Blanco se encargará de desvelar los secretos y dudas más comunes de las rejillas en programas de escritorio (Windows Forms), mientras que yo me encargaré de hacer lo propio con el control GridView de ASP.NET para desarrollo Web. Será una hora para cada control con contenidos eminentemente prácticos (mucha demo) y trataremos de resolver las dudas más comunes que se suscitan en los foros de MSDN.


Apúntate pulsando sobre la imagen de más arriba.

Cómo evitar que la sesión caduque por inactividad

Siguiendo con esta mini-serie (parte I y parte II) sobre el mantenimiento de las sesiones en ASP.NET, en esta ocasión me voy a centrar en cómo evitar que una sesión caduque por inactividad mientras el usuario tenga el navegador abierto. Esta situación puede ser deseable en muchas ocasiones.


Por ejemplo, nada fastidia más que estar redactando en el navegador directamente un artículo para un boletín o un blog (como es el caso) y que cuando vas a enviarlo y pulsas el botón «Publicar» te salga un mensaje diciéndote que la sesión ha caducado (y por supuesto has perdido todo lo que escribiste). En este caso es interesante que la página de edición mantenga la sesión viva mientras tú estás trabajando en ella, aunque te vayas a comer y vuelvas dos horas más tarde. Este caso se da por ejemplo en aplicaciones como nuestro servicio MAILCast®, en el que hemos implementado una solución similar a la que describiré ahora.


Otro ejemplo lo tenemos en servicios como nuestra plataforma de teleformación SELF, con la que impartimos los cursos de campusMVP. Si un alumno está parado en una lección que contiene por ejemplo un vídeo cuya duración es de media hora (la sesión normal dura 20 minutos) o que tiene un laboratorio que va siguiendo paso a paso y tarda una hora en hacerlo, cuando finalmente quiera pasar al siguiente punto del índice se encontraría con la desagradable sorpresa de que la sesión ha caducado y que por lo tanto debería volver a autenticarse en el sistema. Esto no es aceptable claramente, así que tenemos que buscar una solución para evitarlo.


Lo primero que se le suele ocurrir a todo el mundo es aumentar el tiempo de caducidad de sesión bien tocando la configuración de IIS (mala cosa pues afecta a toda la aplicación) o bien aumentándolo para una página específica. El probvlema que tiene esto es que nunca sabes cuánto es un tiempo razonable y que además en muchas ocasiones variará enormemente de unas páginas a otras al ofrecer éstas contenido dinámico. Además si luego realmente el usuario no permanece en la página y se limita a cerrar el navegador, la sesión se quedará ocupando memoria y recursos del servidor durante mucho rato sin necesidad alguna. Así que alguna forma mejor tiene que haber…


Lo cierto es que conseguirlo es muy fácil. ¿Cómo se consigue de manera natural que una sesión se mantenga activa?, pues como sabemos recibiendo peticiones del usuario en el servidor, las cuales renuevan el periodo de caducidad en cada petición.


Pues entonces la solución está clara: vamos a lanzar peticiones al servidor en segundo plano usando JavaScript, de forma que se reciban en el servidor y mantengan la sesión activa. Ni más ni menos.


Para ello una forma habitual de hacerlo sería usar el objeto XmlHttpRequest en el que se basan las aplicaciones AJAX, si bien como veremos enseguida ni siquiera hace falta complicarse tanto.


El «truco» es que el recurso que llamemos en el servidor no puede ser cualquiera, sino que tiene que ser alguno que pase por el «pipeline» de ASP.NET que incluya gestión de sesiones. Lo mejor, por tanto, es llamar a una página .ASPX o a un manejador .ASHX.


La llamada la podemos hacer usando un simple script que solicite más script al servidor, con un código similar a este:


//Ejecuta el script en segundo plano evitando así que caduque la sesión de esta página
function MantenSesion()
{                
    var CONTROLADOR = «refresh_session.ashx»;
    var head = document.getElementsByTagName(‘head’).item(0);            
    script = document.createElement(‘script’);            
    script.src = CONTROLADOR ;
    script.setAttribute(‘type’, ‘text/javascript’);
    script.defer = true;
    head.appendChild(script);
}

Con esto lo que hacemos es crear un nuevo script en la cabecera de la página y añadirlo al DOM del navegador, momento en el cual se solicitará al servidor. El origen del script en este caso es un simple manejador ASHX (que debe implementar la interfaz IRequiresSessionState para que se tenga acceso a la sesión y por lo tanto entre en el proceso el proveedor de sesiones) y que devuelve en este caso un simple comentario de script, ya que lo único que buscamos es que se mantenga activa la sesión gracias a la petición.


Podemos conseguir algo similar usando un iframe oculto al que mediante script le cambiamos la propiedad «src» para que pida una página ASPX del servidor la cual se devuelve vacía pero nos sirve para el mismo propósito. Es decir, no es necesario recurrir a técnicas más sofisticadas como la de XmlHttpRequest y nos aseguramos que funcionará hasta en navegadores bastante antiguos.


La otra cosa que hay que considerar es el intervalo de tiempo que usaremos para llamar a esta función de JavaScript que mantendrá la sesión viva. Si la sesión dura 20 minutos podemos llamar cada 18 minutos o así (para asegurar) y así no impactará demasiado en el servidor que mandemos estas peticiones extra pues son muy escasas. Por lo tanto la mejor forma de proceder es establecer un temporizador que llame a dicha función por ejemplo cada el 90% de la duración de la sesión de ASP.NET. Se consigue de forma muy sencilla simplemente añadiendo un código como este al final de nuestra página ASPX:



<script language=»javascript» type=»text/javascript»>
    setInterval(‘MantenSesion()’, <%= (int) (0.9 * (Session.Timeout * 60000)) %>);
</script>


Así lo que conseguimos es crear un temporizador que se repetirá cada ‘x’ milisegundos y que llamará a la anterior función para mantener la sesión abierta. Se multiplica por 60.000 el tiempo de sesión porque éste está expresado en segundos y el intervalo del temporizador debe ir en milisegundos. En el caso del tiepo de sesión por defecto (20 minutos) este código generaría un temporizador que renovaría la sesión cada 1.080.000 milisegundos, o sea, cada 18 minutos.


Como vemos es muy fácil de conseguir y puede resultar muy útil en ocasiones.


¡Espero que te sirva!


ACTUALIZACIÓN DÍA 5/5/2009


He añadido aquí, un vídeo práctico y código de ejemplo de cómo implementar esto.

Cómo detectar si la sesión ha caducado en ASP.NET (Método II)

En mi anterior post comentaba brevemente el funcionamiento más común de los sistemas de sesiones de los servidores de aplicaciones Web y en particular el de ASP y ASP.NET. Éste lleva acarreados una serie de problemas cuando ls sesiones terminan por lo que comentaba una forma sencilla de detectar que una sesión había caducado. En dicho post comenté que iba a explicar una forma más «profesional» y autocontenida de comprobar si una sesión está activa o no en ASP.NET, y a eso voy…


El mecanismo para comprobar si la sesión actual está caducada o no pasa por el uso de una propiedad no muy conocida de la clase HttpContext: IsNewSession. Esta propiedad devuelve ‘verdadero’ únicamente cuando se acaba de crear una sesión para el usuario justo en la petición actual. Una sesión se crea cuando se crea una variable de sesión por primera vez. Al hacerlo se envía al cliente una cabecera con el identificador de sesión que es el que posteriormente el navegador envía de nuevo al servidor en cada petición, permitiendo así detectar a qué sesión pertenece dicha petición (suena más complicado de lo que es). Esta cabecera es realmente una cookie que sólo se mantiene activa mientras dura la sesion (cookie de sesión) ya que nunca se persiste a disco. La cookie se identifica con el nombre «ASP.NET_SessionId«.


El navegador no es consciente de si la sesión ha caducado o no en el servidor, por lo tanto sigue enviando todo el tiempo la cabecera sin saber si realmente vale para algo. El sistema de detección de la sesión caducada se basa en que, cuando la sesión caduca, en la siguiente petición que se haga al servidor se crea una nueva sesión. A diferencia de la primera vez en la que se crea la sesión, cuando ésta caduca ya existe la cebecera «ASP.NET_SessionId» en las peticiones del navegador. Por lo tanto una petición cuya sesión acaba de caducar es aquella en la que se crea una nueva sesión pero al mismo tiempo existe esta cabecera en la petición.


Puesto en forma de código esta condición se expresa de modo similar a este:

    public static bool IsSessionTimedOut()
{
HttpContext ctx = HttpContext.Current;
if (ctx == null)
throw new Exception(«Este método sólo se puede usar en una aplicación Web»);

//Comprobamos que haya sesión en primer lugar
//(por ejemplo si por ejemplo EnableSessionState=false)
if (ctx.Session == null)
return false; //Si no hay sesión, no puede caducar
//Se comprueba si se ha generado una nueva sesión en esta petición
if (!ctx.Session.IsNewSession)
return false; //Si no es una nueva sesión es que no ha caducado

HttpCookie objCookie = ctx.Request.Cookies[«ASP.NET_SessionId»];
//Esto en teoría es imposible que pase porque si hay una
//nueva sesión debería existir la cookie, pero lo compruebo porque
//IsNewSession puede dar True sin ser cierto (más en el post)
if (objCookie == null)
return false;

//Si hay un valor en la cookie es que hay un valor de sesión previo, pero como la sesión
//es nueva no debería estar, por lo que deducimos que la sesión anterior ha caducado
if (!string.IsNullOrEmpty(objCookie.Value))
return true;
else
return false;
}


He incluido comentarios para que sea más fácil seguir la lógica.


Como vemos lo primero que se hace es obtener una referencia al contexto actual de la petición Web (si no existe es que no estás usando este método en una petición Web). Lo siguiente que se hace es comprobar si hay sesión. No siempre existe ya que se puede desconectar la gestión de sesiones en la página o en toda la aplicación (a través de un ajuste en web.config). Luego es cuando viene lo que expliqué en el párrafo anterior: se comprueba si hay una nueva sesión con IsNewSession. Siendo así se obtiene una referencia a la cookie de sesión. Si no existe es que es la primera vez que se crea la sesión para este usuario, pero si existe y contiene algún valor es que existió una sesión anterior y por lo tanto, al estar creándola de nuevo, se había caducado.


He dejado este código en una clase llamada SessionTimeOut para que si tienes interés te la bajes directamente lista para usar.


En el próximo post comentaré casi lo contrario a esto: cómo conseguir que la sesión no caduque mientras el usuario tenga el navegador abierto, aunque no haga petición alguna en mucho rato y sin ampliar el tiempo de sesión ad infinitum, lo cual tiene muchas aplicaciones prácticas.

Cómo detectar si la sesión ha caducado en ASP.NET (Método I)

El protocolo HTTP es un protocolo sin estado. Esto quiere decir que no hay forma incluída en el protocolo para discernir una petición de otra. Por lo tanto cuando llegan dos peticiones al servidor no hay forma de saber si pertenecen al mismo usuario (ni siquiera la IP como alguna gente me dice a veces, ya que muchas personas pueden salir a Internet desde la misma dirección IP (mismo router y conexión). Además los identificacdores estáticos como ese no son fiables nunca).


Dicho esto, lo que está claro es que en la práctica sí que existe forma de distinguir que dos peticiones vienen del mismo usuario. Es el concepto que sostiene las sesiones de ASP.NET y otras tecnologías. ¿Cómo se consigue?. Bueno, existen muchas formas de hacerlo, pero la más habitual consiste en utilizar una cookie de sesión para almacenar un valor único que identifica de manera inequívoca a cada usuario. Estas cookies de sesión son realmente cabeceras HTTP que el navegador envía de vuelta al servidor en cada petición que hace al mismo. Un módulo especializado en el lado servidor lee estas cabeceras e inicializa en cada petición el contexto de la sesión correspondiente. Es por ello que luego podemos usar de manera natural el objeto Session (de la clase HttpSession), que nos da la ilusión de que disponemos de un ámbito de almacenamiento atado al usuario actual que se conserva entre peticiones. No voy a entrar en más detalles ya que cualquier programador experimentado con ASP.NET está familiarizado con este concepto.


Al trabajar con sesiones almacenamos en variables de sesión valores que queremos conservar entre peticiones para cada usuario. Para conservar los recursos del servidor estos valores se almacenan sólo durante un tiempo determindo tras el cual si no hay nuevas peticiones se eliminan. En cada nueva petición este tiempo de vida se prorroga pudiendo mantener la sesión «activa» mientras haya actividad. En ASP.NET/IIS, por defecto las sesiones tienen un tiempo de validez de 20 minutos. Si pasan más de 20 minutos desde la última petición de un usuario la sesión correspondiente a éste se termina, eliminándose de memoria toda la información acumulada.


Y ahí radica precisamente un problema muy habitual de muchos programadores, ya que al caducar la sesión de repente muchas cosas pueden dejar de funcionar, ya que información que necesitábamos deja de estar disponible. El problema no suele ser si está disponible o no, sino si no está disponible porque nunca se estableció o por que la sesión ha caducado eliminándola. Con toda seguridad cualquier programador experimentado de ASP o ASP.NET (o, incluso, otras tecnologías como PHP) se ha encontrado en una situación similar en mútliples ocasiones.


¿Existe alguna forma de determinar si la sesión actual ha caducado?


Pues sí. De hecho hay varios. Ahora voy a contar uno bastante obvio y rápido de implementar, si bien algo «pedrestre» y engorroso pues implica una coordinación entre dos partes de la aplicación.


Consiste en algo bastante obvio y que consiste en establecer una variable de sesión automáticamente al iniciar ésta (en el evento Session_Start que se lanza en ese momento). Más tarde basta con comprobar si esta variable única está establecida o no para saber si, en efecto, ésta sigue activa. Sería así:

    void Session_Start(object sender, EventArgs e)
{
Session[«Activa»] = true;
}

Luego podemos comprobar si esta variable es nula o no para decidir si la sesión está activa, ya que la variable existirá siempre que exista la sesión. Muy fácil.


No obstante es un método algo «chapuzas» porque hay que acordarse de establecer la variable en el evento Session_Start en el archivo Global.asax, y luego estar leyéndola por ahi para comprobarlo.


Así que para remediarlo en el próximo post contaré la forma de averiguarlo de modo mucho más «profesional», en un método auto-contenido e independiente que para averiguarlo se basa en el funcionamiento del sistema de sesiones basado en cookies de sesión. En un siguiente post hablaré de (casi) lo contrario: cómo mantener la sesión abierta indefinidamente sin necesidad de aumentar el tiempo de sesión.


¡Hasta pronto!

He estado muy "missing" pero estoy empezando a volver…

Hoy hace exactamente un mes que no publicaba nada en el blog. Me fastidia, y tengo muchas cosas interesantes en la recámara esperando a tener un rato para publicarlas, pero es que he tenido (y tengo) una temporada muy mala. O muy buena, según se mire.


Estoy trabajando «a dolor» en el nuevo catálogo de cursos de campusMVP, que verá la luz en làs próximas semanas. Espero que os guste, porque vamos a pegar el cambio más grande en el proyecto desde que nació. Un currazo. Ya os iréis enterando, pero os va a gustar 🙂 Iremos sacando varias cosas nuevas poco a poco, algunas creo que de gran interés.


Sobrecarga de trabajoTambién he estado muy liado preparando un curso de e-mail marketing que he impartido a varios clientes tanto presencialmente como en directo a través de Internet. Además he tardado más de lo normal porque he procurado ser muy ordenado y sistemático, ya que este curso constituye la base para un libro sobre el tema que hace un año que tengo en proyecto, y que espero que vea la luz antes de final de año (bastante antes espero, de hecho). Ya os lo contaré también aquí.


Además he hecho la beta de uno de los nuevos exámenes de certificación, he estado actualizando material para mis cursos on-line de campusMVP (me falta poquito para acabar), algún artículo para PC World y dotNetMania que estoy terminando también, escribiendo posts en inglés y castellano para TheEmailingExperience y otro blog que de momento es privado (y un día de estos se hará público, espero), coordinando nuevos libros de Krasis Press que verán la luz en los próximos meses, he asisitido (como alumno) un curso de 3 días sobre management en Madrid, me ha tocado el grupo de alumnos más demandante de la historia de campusMVP que me han tenido y me tienen contestando dudas duramente desde hace bastantes semanas (sois unos cracks, pero me alegraré cuando terminéis, jajaja), he estado de cumpleaños (y por lo tanto de juerga también)…


Y por supuesto tengo una empresa que dirigir y una familia a la que hacerle caso, así que como comprenderéis alguna cosa tenía que dejar un poco de lado. Y esta vez le ha tocado a este blog personal.


Desde aquí quiero pedirle disculpas también a mis trabajadores (mucho mejor dicho, mis compañeros de trabajo, sufridores de mi «hurañismo») porque no he podido hacerles apenas caso, mucho menos que de costumbre, que ya es decir. Sois unos «crases». Espero poder compensaros.


El la foto de este post no soy yo, pero podría serlo perfectamente 🙂


A partir de hoy retomaré la actividad bloguera habitual (o casi) y procuraré publicar unas cuantas cosas interesantes como de costumbre.


¡Nos vemos!


JM.