cookies asp.net, autenticación y tiempos de espera de sesión

Tengo un sitio web asp.net que usa autenticación de formularios. Hay algunas cosas que guardo en sesiones como nombre de usuario, ID de usuario, correo electrónico, etc.

Permito que el usuario permanezca conectado al sitio estableciendo una fecha de vencimiento larga en la cookie de autenticación. Por lo tanto, es muy común que la sesión expire mientras el usuario todavía está autenticado.

El problema al que me estoy enfrentando es que a veces la sesión del usuario agota el tiempo de espera pero aún están autenticados. Entonces, por ejemplo, una de mis páginas de usuario (que requiere autenticación) dirá “Bienvenido Mike” cuando su sesión esté activa, pero una vez que caduque dirá “Bienvenido [en blanco]” porque la información ya no está en la sesión, sin embargo, todavía están autenticados

¿Cuál es la mejor manera de manejar esto? ¿Debo sincronizar la información de la sesión cuando la información ya no está allí? ¿O debería mover la información del usuario (nombre de usuario, ID de usuario, correo electrónico) a las cookies y no preocuparme por los tiempos de espera de las sesiones?

No quiero establecer la duración de la sesión en algo así como 60 minutos o más. Lo que quiero es que mis usuarios puedan iniciar sesión una vez y no tener que volver a iniciar sesión hasta que cierren la sesión de forma explícita.

Evite usar la sesión tanto como pueda, si puede escapar sin tener una visión, hace que las implementaciones de varios servidores sean un poco más fáciles. Probablemente, el nombre y el correo electrónico son candidatos fáciles para las cookies. Es fácil falsificar una cookie, por lo que el ID de usuario puede no ser una buena idea según sus necesidades de seguridad.

Las cookies de autenticación de formularios están encriptadas y puede agregar datos adicionales a esas cookies (consulte los detalles a continuación). Es probable que sea pirateable pero no tan fácil como una simple cookie.

Aquí está el código que he usado en el pasado ligeramente modificado para eliminar algunos detalles específicos del proyecto. Llámalo en el evento LoggedIn del control de inicio de sesión.

void AddUserIDToAuthCookie(string userID) { //There is no way to directly set the userdata portion of a FormAuthenticationTicket //without re-writing the login portion of the Login control // //I find it easier to pull the cookie that the Login control inserted out //and create a new cookie with the userdata set HttpCookie authCookie = Response.Cookies[AUTH_COOKIE]; if(authCookie == null) { return; } Response.Cookies.Remove(AUTH_COOKIE); FormsAuthenticationTicket oldTicket = FormsAuthentication.Decrypt(authCookie.Value); var newTicket = new FormsAuthenticationTicket(oldTicket.Version, oldTicket.Name, oldTicket.IssueDate, oldTicket.Expiration, oldTicket.IsPersistent, userID, oldTicket.CookiePath); authCookie.Value = FormsAuthentication.Encrypt(newTicket); Response.Cookies.Add(authCookie); } 

FYI, copié esto de un proyecto anterior y lo edité aquí para eliminar algunos bits específicos del proyecto, por lo que es posible que no compile, pero estará muy cerca.

Para obtener la identificación en su página web …

 FormsAuthenticationTicket ticket = ((FormsIdentity) Page.User.Identity).Ticket; string id = ticket.UserData; 

Usé este mecanismo para almacenar una identificación que no era parte de los datos del usuario aspnetdb. Si aspnetdb maneja todos sus datos de identidad, es posible que solo necesite acceder al objeto Page.User.Identity.

Personalmente, mantendría los 20 minutos predeterminados y agregaría una funcionalidad de “mantener vivo” a su sitio. Realice un javascript simple que sondea, digamos heartbeat.aspx, cada 5 minutos para mantener la sesión activa. Esto extenderá la sesión y la autenticación sin guardar los locos tokens de autenticación.

Hay algunos ejemplos (malos en mi opinión) de cómo hacer esto. Terminé usando algo basado en la prevención de tiempo de espera de sesión de AjaxLines . Sin embargo, en lugar de usar la biblioteca ajax, simplemente usé una solicitud xhtml directamente. No se necesita nada más que una llamada progtwigda de javascript a un GET en la página de heartbeat.

Técnicamente debido al tiempo de espera de la sesión de asp.net, su usuario no debería desconectarse. Esto debe / está controlado por la cookie de autenticación de formularios.

Toda la información esencial relacionada con la autenticación del usuario debe mantenerse en la propiedad USERDATA del ticket de autenticación de formularios. Este valor no se debe mantener en sesión como sesión.

Solo mantén esos valores en sesión que sean recreables.

Entonces, cuando crea una cookie de autenticación de formularios, puede pasar toda la información esencial como parte del ticket.

Lo más rápido que puede hacer es mantener igual el tiempo de espera de la autenticación tanto de sesión como de formularios. Esta será una buena práctica para hacer.

El tiempo de espera de la sesión se extiende automáticamente con cada solicitud al sitio.

Mientras que una autenticación Forms extiende su tiempo solo después de que ha transcurrido el 50% del tiempo.

Aquí hay información detallada sobre esto … Preguntas frecuentes sobre la autenticación de formularios

El HttpModule es un buen lugar para hacerlo. De esta forma, su tiempo de espera siempre estará sincronizado, aunque puede haber una pequeña brecha.

También mantenga el tiempo de espera tanto de autenticación de sesión como de autenticación de formularios. Esta será una buena práctica para hacer.

El tiempo de espera de la sesión se extiende automáticamente con cada solicitud al sitio.

Mientras que una autenticación Forms extiende su tiempo solo después de que ha transcurrido el 50% del tiempo.

Lo más simple es extender el tiempo de autenticación de Forms en una página HttpModule o base personalizada, sea cual sea su diseño.

De esta forma, su tiempo de espera siempre estará sincronizado, aunque puede haber una pequeña brecha.

Sin intentar nada por mí mismo, hay algunas cosas que vería.

  • Use un método / sobrecarga de la clase FormsAuthentication que le permite establecer una cookie persistente. Sin embargo, en mi humilde opinión, es de cortesía común que los usuarios elijan marcar la casilla “recordarme” en lugar de forzarlos a que inicien sesión de forma persistente. Hay varios métodos que le permiten hacer esto en función del comportamiento que desee: SetAuthenticationCookie () y RedirectFromLoginPage () son los primeros en pensar.

  • Echa un vistazo a FormsAuthentication.GetAuthenticationCookie (). Esto generará una cookie HTTP con el token de autenticación, pero no lo configurará realmente, lo que le permitirá cambiar lo que desee, aunque si el módulo FormsAuthentication está buscando un valor específico, jugar con él podría romper la autenticación. A continuación, deberá agregar la cookie a la colección de cookies en la respuesta de forma manual.

Mi método preferido es usar sesión como caché. es decir, intente leer desde la sesión, si el valor está allí, luego devuélvalo, si no es así, léalo desde el almacén de persistencia (base de datos, etc.), póngalo en sesión y devuélvalo.

Para simplificar esto, cree una clase, agregue una propiedad para cada variable en sesión y almacene una instancia de la clase en sesión. Luego crea un método estático para obtener una instancia de la clase. Agregaré un ejemplo más adelante si pudiera.