2013-09-27 11 views
6

Io sono l'attuazione di una struttura di sessione.Come affrontare la sessione lasciata aperta

Ho un ConcurrentDictionary sul lato server che tiene su tutte le coppie <SessionId, UserSession>.

Quando viene stabilita una nuova connessione, un cookie viene assegnato a un browser client, perm o temp a seconda dell'opzione RememberMe.

Quando i clienti chiamano la funzione LogOut si toglie la sessione dal dizionario.

Tuttavia, quando il browser client viene semplicemente chiuso o arrestato in modo anomalo e il cookie è stato perso, scaduto o cancellato, l'oggetto sessione lato server in memoria è rimasto nel dizionario e diventa un fantasma. Col passare del tempo questi fantasmi si accumuleranno.

La mia domanda è, come migliorare la progettazione in modo che le sessioni di morti possono essere puliti dopo che sono scaduti?

ho pensato di fare un servizio timer l'esecuzione di un programma di pulizia, ma non si sente elegante. C'è un modo più semplice per farlo senza dipendere da un servizio esterno?

+1

Sarebbe preferibile utilizzare una cache con un termine di laminazione, o gestire il metodo Session_End. Cosa stai memorizzando in UserSession? – zimdanen

+0

Non esiste un metodo Session_End affidabile da gestire, se il browser del client si arresta in modo anomalo, finisce semplicemente lì senza tornare al server. Ma ora che hai citato un cache, ho avuto un'idea, posso memorizzare un elenco ordinato per il tempo LastActive. Ogni volta che un nuovo client esegue l'accesso, può aiutare a controllare la prima sessione in coda e rimuoverla se scaduta. Ogni utente attivo si metterà in coda alla coda quando chiama il server per fare qualcosa. Quindi, diventa l'ultima persona attiva. – Tom

+0

A un certo punto, hai bisogno di vedere i dati di tutti quelli che hanno effettuato l'accesso? In caso contrario, perché non archiviare i dati in Session (se sono necessari i dati) e lasciarli scomparire al termine della sessione? Ciò gestirà anche la pressione della memoria eliminando gli elementi dalla sessione se c'è pressione. O utilizzare HttpContext.Cache con un timeout di rollover, quindi scomparirà dopo un intervallo di tempo dopo l'ultimo accesso. (Fondamentalmente, non è necessario eseguire il rollover.) – zimdanen

risposta

4

ho una situazione simile in uno dei miei progetti.

invece di dizionario, ho usato la cache con una breve assoluta di scadenza e ID di sessione di utente come la mia chiave di cache:

HttpContext.Current.Cache.Insert(sessionID, userEntity, null, DateTime.Now.AddSeconds(30), TimeSpan.Zero); 

e nel lato client, io faccio una chiamata AJAX, ogni 15 secondi, per notifica al server e rinnova la cache per quell'ID di sessione.

così ogni volta che un utente chiude la sua finestra del browser, il server non riceve alcuna notifica e id di sessione dell'utente scaduto automaticamente.

+0

Grazie, ha fatto qualche ricerca seguendo l'idea, realizzato System.Runtime.Caching in .NET4 sopra sembra essere la strada da percorrere. http://bartwullems.blogspot.com.au/2011/02/caching-in-net-4.html – Tom

0

sto rispondendo alla mia domanda dopo pochi mesi. Se voglio avere una struttura del genere, utilizzerei Microsoft SignalR. Perché controlla le sessioni per me in tempo reale e fa molto di più.

+0

Perché stai ancora utilizzando sessioni per l'autenticazione degli utenti. Questo metodo era una soluzione valida per l'era ASP classica ma non più. Si dovrebbe considerare l'utilizzo dell'autenticazione Forms ASP.NET invece che è un approccio preferenziale in ASP.NET World. – VahidN

2

Se il sessionstate è "InProc", perché non basta applicare il codice in Session_Start e Session_End?

void Session_Start(object sender, EventArgs e) 
{ 
    //Add to ConcurrentDictionary 
} 

void Session_End(object sender, EventArgs e) 
{ 
    // 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. 

    //Remove from ConcurrentDictionary 
}