Redireccionamiento Push ASP.NET en el tiempo de espera de la sesión

Estoy buscando un tutorial, entrada de blog, o algo de ayuda sobre la técnica detrás de los sitios web que automáticamente empujan a los usuarios (es decir, sin una devolución de datos) cuando expira la sesión. Cualquier ayuda es apreciada

    Por lo general, establece el tiempo de espera de la sesión y puede agregar un encabezado de página para redirigir automáticamente la página actual a una página donde borre la sesión justo antes del tiempo de espera de la sesión.

    De http://aspalliance.com/1621_Implementing_a_Session_Timeout_Page_in_ASPNET.2

    namespace SessionExpirePage { public partial class Secure : System.Web.UI.MasterPage { public int SessionLengthMinutes { get { return Session.Timeout; } } public string SessionExpireDestinationUrl { get { return "/SessionExpired.aspx"; } } protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); this.PageHead.Controls.Add(new LiteralControl( String.Format("", SessionLengthMinutes*60, SessionExpireDestinationUrl))); } } } 

    El SessionExpireDestinationUrl debe vincular a una página donde borre la sesión y cualquier otro dato del usuario.

    Cuando el encabezado de actualización caduque, los redirigirá automáticamente a esa página.

    Realmente no se puede “empujar” a un cliente desde su sitio web. Su sitio responderá a las solicitudes del cliente, pero eso es realmente.

    Lo que esto significa es que necesita escribir algo en el lado del cliente (Javascript) que determinará cuándo el usuario ha agotado el tiempo de espera, probablemente al comparar la hora actual con la hora más reciente que tienen en una cookie de sitio (que actualiza con la actual cada vez que el usuario visita una página en su sitio), y luego redirigir si la diferencia es mayor que cierta cantidad.

    (Noto que algunas personas defienden simplemente crear un script que reenvíe al usuario después de una cierta cantidad de tiempo en una página. Esto funcionará en el caso simple, pero si el usuario tiene dos ventanas abiertas en el sitio, y está usando una ventana mucho, y la otra ventana no demasiado, la no tan grande redirigirá de repente al usuario a la página de reenvío, aunque el usuario haya estado constantemente en el sitio. Además, no está realmente sincronizado. con cualquier sesión de mantenimiento que está haciendo en el lado del servidor. Por otro lado, es ciertamente más fácil de codificar, y si eso es lo suficientemente bueno, ¡genial!)

    En la sección , use una etiqueta de actualización META como esta:

      

    donde 0000 es el tiempo de espera de su sesión en segundos y target_page.html la dirección de la página a la que se redirigirá.

    Usando la clase Custom Page y Javascript también podemos lograrlo.

    Cree una clase de base de página personalizada y escriba los códigos de funcionalidad comunes en esta clase. A través de esta clase, podemos compartir las funciones comunes a otras páginas web. En esta clase, necesitamos heredar la clase System.Web.UI.Page . Coloque el siguiente código en la clase Pagebase

    PageBase.cs

     namespace AutoRedirect { public class PageBase : System.Web.UI.Page { protected override void OnPreRender(EventArgs e) { base.OnPreRender(e); AutoRedirect(); } public void AutoRedirect() { int int_MilliSecondsTimeOut = (this.Session.Timeout * 60000); string str_Script = @" "; ClientScript.RegisterClientScriptBlock(this.GetType(), "Redirect", str_Script); } } } 

    Por encima de la función AutoRedirect se utilizará para redirigir la página de inicio de sesión cuando la sesión caduque, utilizando javascript window.setInterval , This window.setInterval ejecuta una función javascript repetidamente con un retraso de tiempo específico. Aquí estamos configurando el retraso de tiempo como valor de tiempo de espera de la sesión. Una vez que se alcanza el tiempo de expiración de la sesión, automáticamente ejecuta la función de redireccionamiento y controla la transferencia a la página de inicio de sesión.

    OriginalPage.aspx.cs

     namespace appStore { public partial class OriginalPage: Basepage { protected void Page_Load(object sender, EventArgs e) { } } } 

    OriginalPage.aspx

     < %@ Page Language="C#" AutoEventWireup="true" CodeFile="OriginalPage.aspx.cs" Inherits="AutoRedirect.OriginalPage" %> 

    Web.config

        

    Nota: la ventaja de usar Javascript es que podría mostrar un mensaje personalizado en el cuadro de alerta antes de location.href, que tendrá mucho sentido para el usuario. En caso de que si no quieres usar Javascript, también puedes elegir la meta redirección

     public void AutoRedirect() { this.Header.Controls.Add(new LiteralControl( String.Format("", this.Session.Timeout * 60, "login.aspx"))); } 

    Estoy usando MVC3 ASp.net como principiante, probé muchas soluciones para resolver mi problema de sesión (ya que estoy usando la variable de sesión en mi código, y después del tiempo de espera no tuve valores de sesión mientras lo sigo usando y Solo encontré que mi problema estaba en el archivo de configuración. El tiempo de espera entre Authentication y sessionState debería ser tan cercano. Así que mataron (vacían) al mismo tiempo // agregan timeout 1 y 2 para probar … deben ser al menos 29 y 30

    Utilicé otras formas en las que también funciona:

    Empezando desde :

      protected void Session_Start(object src, EventArgs e) { if (Context.Session != null) { if (Context.Session.IsNewSession)//|| Context.Session.Count==0) { string sCookieHeader = Request.Headers["Cookie"]; if ((null != sCookieHeader) && (sCookieHeader.IndexOf("ASP.NET_SessionId") >= 0)) { //if (Request.IsAuthenticated) FormsAuthentication.SignOut(); Response.Redirect("/Account/LogOn"); } } } } protected void Session_End(object sender, EventArgs e) { //Code that runs when a session ends. //Note: The Session_End event is raised only when the sessionstate mode //is set to InProc in the Web.config file. If session mode is set to StateServer //or SQLServer, the event is not raised. Session.Clear(); } 

    Y:

     public class SessionExpireFilterAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { HttpContext ctx = HttpContext.Current; // check if session is supported if (ctx.Session != null) { // check if a new session id was generated if (ctx.Session.IsNewSession) { // If it says it is a new session, but an existing cookie exists, then it must // have timed out string sessionCookie = ctx.Request.Headers["Cookie"]; if ((null != sessionCookie) && (sessionCookie.IndexOf("ASP.NET_SessionId") >= 0)) { ctx.Response.Redirect("~/Home/LogOn"); } } } base.OnActionExecuting(filterContext); } } 

    E incluso trabajó con Ajax para resolver el problema de la sesión:

      protected override void OnActionExecuting(ActionExecutingContext filterContext) { if (Session.Count == 0 || Session["CouncilID"] == null) Response.Redirect("/Account/LogOn"); if (Request.IsAjaxRequest() && (!Request.IsAuthenticated || User == null)) { filterContext.RequestContext.HttpContext.Response.StatusCode = 401; } else { base.OnActionExecuting(filterContext); } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)] public class AuthorizeUserAttribute : AuthorizeAttribute { protected override bool AuthorizeCore(HttpContextBase httpContext) { if (!httpContext.Request.IsAjaxRequest()) {//validate http request. if (!httpContext.Request.IsAuthenticated || httpContext.Session["User"] == null) { FormsAuthentication.SignOut(); httpContext.Response.Redirect("~/?returnurl=" + httpContext.Request.Url.ToString()); return false; } } return true; } protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { if (filterContext.HttpContext.Request.IsAjaxRequest()) { filterContext.Result = new JsonResult { Data = new { // put whatever data you want which will be sent // to the client message = "sorry, but you were logged out" }, JsonRequestBehavior = JsonRequestBehavior.AllowGet }; } else { base.HandleUnauthorizedRequest(filterContext); } } } 

    Simplemente copie y pegue este fragmento de código en su archivo Web.Config:

         

    Puede poner esta línea en su Sitio. Maestro:

     Response.AppendHeader("Refresh", Convert.ToString((Session.Timeout * 60)) + ";URL=~/Login.aspx"); 

    Lamentablemente no se puede hacer. El tiempo de espera de la sesión solo ocurre en el lado del servidor y no lo detectará hasta que el usuario realice algún tipo de acción posterior a la publicación.

    Sin embargo, lo que PUEDE hacer es inyectar código de encabezado HTML o JavaScript que automáticamente empujará al usuario a una página de cierre de sesión en el mismo marco de tiempo que el tiempo de espera de su sesión. Esto no garantiza una sincronización perfecta, y puede tener problemas si su usuario está haciendo algunos ítems que requieren mucho tiempo y no está reiniciando el reloj.

    Normalmente agrego este código a mis eventos Page_Load para lograr esto.

     ' Register Javascript timeout event to redirect to the login page after inactivity Page.ClientScript.RegisterStartupScript(Me.GetType, "TimeoutScript", _ "setTimeout(""top.location.href = 'Login.aspx'""," & _ ConfigurationManager.AppSettings("SessionTimeoutMilliseconds") & ");", True) 

    Y si usa el siguiente controlador de inicio de sesión, lo enviará a la URL solicitada antes de iniciar sesión:

      [HttpPost] public ActionResult LogOn(LogOnModel model, string returnUrl) { if (ModelState.IsValid) { if (Membership.ValidateUser(model.UserName, model.Password)) { FormsAuthentication.SetAuthCookie(model.UserName, model.RememberMe); if (Url.IsLocalUrl(returnUrl) && returnUrl.Length > 1 && returnUrl.StartsWith("/") && !returnUrl.StartsWith("//") && !returnUrl.StartsWith("/\\")) { //return Redirect(returnUrl); if (!String.IsNullOrEmpty(returnUrl)) { return Redirect(returnUrl); } else { return RedirectToAction("Index", "Home"); } } else { return RedirectToAction("Index", "Home"); } } else { ModelState.AddModelError("", "The user name or password provided is incorrect."); } } // If we got this far, something failed, redisplay form return View(model); } 

    Por supuesto, necesita utilizar [Authorize] sobre la clase de controlador o incluso Acción en específico.

     [Authorize] public class MailController : Controller { } 

    Bueno, esto se vuelve complicado para las solicitudes de AJAX como señaló Zhaph – Ben Duguid. Aquí estaba mi solución para hacer que esto funcione con AJAX (usando los controles web de Telerik, pero están construidos usando el kit de herramientas ASP.NET AJAX, creo).

    En pocas palabras, rodé mi propio tipo de sesión de vencimiento deslizante.

    En mi Site.Master, estoy actualizando una variable de sesión en CADA postback (postback o solicitud de AJAX porque las solicitudes de AJAX todavía inician el evento Page_Load):

     protected void Page_Load(object sender, EventArgs e) { if (!this.IsPostBack) { if (this.Request.IsAuthenticated) this.pnlSessionKeepAlive.Visible = true; else this.pnlSessionKeepAlive.Visible = false; } if (this.Session["SessionStartDateTime"] != null) this.Session["SessionStartDateTime"] = DateTime.Now; else this.Session.Add("SessionStartDateTime", DateTime.Now); } 

    Luego, en mi marcado para my site.master, incluí un iframe con una página ASPX que uso “detrás de escena” para verificar y ver si mi expiración deslizante personalizada ha expirado:

       

    Ahora en mi página SessionExpire.aspx, simplemente actualizo la página de vez en cuando y verifico si la marca de tiempo ha caducado y, de ser así, me redirecciona a mi página de logout.aspx que luego determina a qué página de inicio de sesión enviar al usuario:

     public partial class SessionExpire : System.Web.UI.Page { protected void Page_Load(object sender, EventArgs e) { /* We have to do all of this because we need to redirect to 2 different login pages. The default .NET * implementation does not allow us to specify which page to redirect expired sessions, its a fixed value. */ if (this.Session["SessionStartDateTime"] != null) { DateTime StartTime = new DateTime(); bool IsValid = DateTime.TryParse(this.Session["SessionStartDateTime"].ToString(), out StartTime); if (IsValid) { int MaxSessionTimeout = Convert.ToInt32(ConfigurationManager.AppSettings["SessionKeepAliveMins"]); IsValid = (DateTime.Now.Subtract(StartTime).TotalMinutes < MaxSessionTimeout); } // either their session expired or their sliding session timeout has expired. Now log them out and redirect to the correct // login page. if (!IsValid) this.Logout(); } else this.Logout(); // check every 60 seconds to see if the session has expired yet. Response.AddHeader("Refresh", Convert.ToString(60)); } private void Logout() { this.Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "TimeoutScript", "setTimeout(\"top.location.href = '../Public/Logout.aspx'\",\"1000\");", true); } } 

    Muchas gracias a las personas de arriba que publicaron información, esto me llevó a mi solución y espero que ayude a otros.