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.