Mantenere la sessione ASP.NET aperta / triggers

Qual è il modo più semplice e meno intrusivo per mantenere triggers una sessione ASP.NET finché l’utente ha la finestra del browser aperta? Sono chiamate AJAX a tempo? Voglio impedire quanto segue: a volte gli utenti mantengono la loro finestra aperta per un lungo periodo di tempo, quindi inseriscono elementi e all’invio non funziona più perché la sessione lato server è scaduta. Non desidero aumentare il valore di timeout per più di 10 minuti sul server poiché desidero sessioni chiuse (chiudendo la finestra del browser) per scadere rapidamente.

Suggerimenti, esempi di codice?

Uso JQuery per eseguire una semplice chiamata AJAX a un gestore HTTP fittizio che non fa altro che mantenere viva la sessione:

function setHeartbeat() { setTimeout("heartbeat()", 300000); // every 5 min } function heartbeat() { $.get( "/SessionHeartbeat.ashx", null, function(data) { //$("#heartbeat").show().fadeOut(1000); // just a little "red flash" in the corner :) setHeartbeat(); }, "json" ); } 

Il gestore di sessione può essere semplice come:

 public class SessionHeartbeatHttpHandler : IHttpHandler, IRequiresSessionState { public bool IsReusable { get { return false; } } public void ProcessRequest(HttpContext context) { context.Session["Heartbeat"] = DateTime.Now; } } 

La chiave è aggiungere IRequiresSessionState, altrimenti Session non sarà disponibile (= null). Il gestore può ovviamente anche restituire un object serializzato JSON se alcuni dati devono essere restituiti al JavaScript chiamante.

Reso disponibile tramite web.config:

    

aggiunto da balexandre il 14 agosto 2012

Mi è piaciuto così tanto di questo esempio, che voglio migliorare con HTML / CSS e la parte beat

cambia questo

 //$("#heartbeat").show().fadeOut(1000); // just a little "red flash" in the corner :) 

in

 beatHeart(2); // just a little "red flash" in the corner :) 

e aggiungi

 // beat the heart // 'times' (int): nr of times to beat function beatHeart(times) { var interval = setInterval(function () { $(".heartbeat").fadeIn(500, function () { $(".heartbeat").fadeOut(500); }); }, 1000); // beat every second // after n times, let's clear the interval (adding 100ms of safe gap) setTimeout(function () { clearInterval(interval); }, (1000 * times) + 100); } 

HTML e CSS

 
/* HEARBEAT */ .heartbeat { position: absolute; display: none; margin: 5px; color: red; right: 0; top: 0; }

ecco un esempio dal vivo solo per la parte che batte: http://jsbin.com/ibagob/1/

Se si utilizza ASP.NET MVC, non è necessario un gestore HTTP aggiuntivo e alcune modifiche del file web.config. Tutto ciò che serve – solo per aggiungere qualche semplice azione in un controller Home / Common:

 [HttpPost] public JsonResult KeepSessionAlive() { return new JsonResult {Data = "Success"}; } 

, scrivi un codice JavaScript come questo (l’ho messo in uno dei file JavaScript del sito):

 var keepSessionAlive = false; var keepSessionAliveUrl = null; function SetupSessionUpdater(actionUrl) { keepSessionAliveUrl = actionUrl; var container = $("#body"); container.mousemove(function () { keepSessionAlive = true; }); container.keydown(function () { keepSessionAlive = true; }); CheckToKeepSessionAlive(); } function CheckToKeepSessionAlive() { setTimeout("KeepSessionAlive()", 300000); } function KeepSessionAlive() { if (keepSessionAlive && keepSessionAliveUrl != null) { $.ajax({ type: "POST", url: keepSessionAliveUrl, success: function () { keepSessionAlive = false; } }); } CheckToKeepSessionAlive(); } 

e inizializza questa funzionalità chiamando una funzione JavaScript:

 SetupSessionUpdater('/Home/KeepSessionAlive'); 

Notare che! Ho implementato questa funzionalità solo per gli utenti autorizzati (nella maggior parte dei casi non esiste alcun motivo per mantenere lo stato della sessione per gli ospiti) e la decisione di mantenere attivo lo stato della sessione non è solo basata su: browser aperto o no, ma l’utente autorizzato deve svolgere alcune attività sul sito (muovi un mouse o digita un tasto).

Ogni volta che si effettua una richiesta al server, il timeout della sessione viene ripristinato. Quindi puoi semplicemente effettuare una chiamata ajax a un gestore HTTP vuoto sul server, ma assicurati che la cache del gestore sia disabilitata, altrimenti il ​​browser memorizzerà il gestore in cache e non effettuerà una nuova richiesta.

KeepSessionAlive.ashx.cs

 public class KeepSessionAlive : IHttpHandler, IRequiresSessionState { public void ProcessRequest(HttpContext context) { context.Response.Cache.SetCacheability(HttpCacheability.NoCache); context.Response.Cache.SetExpires(DateTime.UtcNow.AddMinutes(-1)); context.Response.Cache.SetNoStore(); context.Response.Cache.SetNoServerCaching(); } } 

JS:

 window.onload = function () { setInterval("KeepSessionAlive()", 60000) } function KeepSessionAlive() { url = "/KeepSessionAlive.ashx?"; var xmlHttp = new XMLHttpRequest(); xmlHttp.open("GET", url, true); xmlHttp.send(); } 

@veggerby – Non è necessario il sovraccarico di memorizzazione delle variabili nella sessione. Basta preformare una richiesta al server è sufficiente.

Hai davvero bisogno di tenere la sessione (ci sono dei dati in esso?) O è sufficiente falsificarlo, riorganizzando la sessione quando arriva una richiesta? Se il primo, utilizzare il metodo sopra. Se il secondo, provare qualcosa di simile utilizzando il gestore di eventi Session_End.

Se si dispone dell’autenticazione basata su form, si ottiene qualcosa nel modo Global.asax.cs

 FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(formsCookie.Value); if (ticket.Expired) { Request.Cookies.Remove(FormsAuthentication.FormsCookieName); FormsAuthentication.SignOut(); ... } else { ... // renew ticket if old ticket = FormsAuthentication.RenewTicketIfOld(ticket); ... } 

E si imposta la durata del ticket molto più a lungo della durata della sessione. Se non si sta effettuando l’autenticazione o si utilizza un metodo di autenticazione diverso, esistono trucchi simili. L’interfaccia Web di Microsoft TFS e SharePoint sembrano utilizzarli: il risultato è che se si fa clic su un collegamento in una pagina obsoleta, vengono visualizzati i prompt di autenticazione nella finestra popup, ma se si utilizza semplicemente un comando, funziona.

puoi semplicemente scrivere questo codice nel tuo file di script java, questo è tutto.

 $(document).ready(function () { window.setInterval(function () { var url = 'put the url of some Dummy page'; $.get(url); },1140000); }); 

Il 1140000 è il tempo di aggiornamento, aggiornerà il timeout della sessione. Il timeout di aggiornamento viene calcolato come timeout predefinito di iis = 20 minuti, significa 20 × 60000 = 1200000 millisecondi – 60000 millisecondi (un minuto prima della scadenza della sessione) è 1140000.

Ecco una soluzione alternativa che dovrebbe sopravvivere se il pc client entra in modalità sospensione.

Se si dispone di una grande quantità di utenti che hanno effettuato l’accesso, utilizzare questa caucanvas poiché potrebbe consumare molta memoria del server.

Dopo aver effettuato l’accesso (lo faccio nell’evento LoggedIn del controllo di accesso)

 Dim loggedOutAfterInactivity As Integer = 999 'Minutes 'Keep the session alive as long as the authentication cookie. Session.Timeout = loggedOutAfterInactivity 'Get the authenticationTicket, decrypt and change timeout and create a new one. Dim formsAuthenticationTicketCookie As HttpCookie = _ Response.Cookies(FormsAuthentication.FormsCookieName) Dim ticket As FormsAuthenticationTicket = _ FormsAuthentication.Decrypt(formsAuthenticationTicketCookie.Value) Dim newTicket As New FormsAuthenticationTicket( ticket.Version, ticket.Name, ticket.IssueDate, ticket.IssueDate.AddMinutes(loggedOutAfterInactivity), ticket.IsPersistent, ticket.UserData) formsAuthenticationTicketCookie.Value = FormsAuthentication.Encrypt(newTicket) 

Ho trascorso alcuni giorni a cercare di capire come prolungare la sessione di un utente in WebForm tramite una finestra di dialogo che consente all’utente di rinnovare la sessione o di lasciarla scadere. La cosa numero 1 che devi sapere è che non hai bisogno di nessuna di queste fantasiose informazioni su “HttpContext” in alcune delle altre risposte. Tutto ciò di cui hai bisogno è $ .post () di jQuery; metodo. Ad esempio, durante il debug ho usato:

 $.post("http://localhost:5562/Members/Location/Default.aspx"); 

e sul tuo sito live useresti qualcosa come:

 $.post("http://mysite/Members/Location/Default.aspx"); 

È così facile. Inoltre, se desideri chiedere all’utente di rinnovare la sessione, procedi come segue:

   

Non dimenticare di aggiungere la finestra di dialogo al tuo html:

   

Ecco la versione del plugin JQuery della soluzione Maryan con ottimizzazione dell’handle. Solo con JQuery 1.7+!

 (function ($) { $.fn.heartbeat = function (options) { var settings = $.extend({ // These are the defaults. events: 'mousemove keydown' , url: '/Home/KeepSessionAlive' , every: 300000 }, options); var keepSessionAlive = false , $container = $(this) , handler = function () { keepSessionAlive = true; $container.off(settings.events, handler) }, reset = function () { keepSessionAlive = false; $container.on(settings.events, handler); setTimeout(sessionAlive, settings.every); }, sessionAlive = function () { keepSessionAlive && $.ajax({ type: "POST" , url: settings.url ,success: reset }); }; reset(); return this; } })(jQuery) 

e come importa nel tuo * .cshtml

 $('body').heartbeat(); // Simple $('body').heartbeat({url:'@Url.Action("Home", "heartbeat")'}); // different url $('body').heartbeat({every:400000}); // different timeout