126 votes

Maintenir la session ASP.NET ouverte / vivante

Quel est le moyen le plus simple et le plus discret de maintenir une session ASP.NET en vie tant que l'utilisateur a la fenêtre du navigateur ouverte ? S'agit-il d'appels AJAX temporisés ? Je veux éviter ce qui suit : parfois les utilisateurs gardent leur fenêtre ouverte pendant un long moment, puis saisissent des données, et à l'envoi, rien ne fonctionne plus parce que la session côté serveur a expiré. Je ne veux pas augmenter la valeur du délai d'expiration de plus de 10 minutes sur le serveur car je veux que les sessions fermées (par la fermeture de la fenêtre du navigateur) expirent rapidement.

Suggestions, exemples de code ?

0 votes

Vous pouvez également consulter ce lien pour obtenir la réponse. dotnetcurry.com/ShowArticle.aspx?ID=453

182voto

veggerby Points 5824

J'utilise JQuery pour effectuer un simple appel AJAX vers un gestionnaire HTTP fictif qui ne fait rien d'autre que de maintenir ma session en vie :

function setHeartbeat() {
    setTimeout("heartbeat()", 5*60*1000); // 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"
    );
}

Le gestionnaire de session peut être aussi simple que :

public class SessionHeartbeatHttpHandler : IHttpHandler, IRequiresSessionState
{
    public bool IsReusable { get { return false; } }

    public void ProcessRequest(HttpContext context)
    {
        context.Session["Heartbeat"] = DateTime.Now;
    }
}

La clé est d'ajouter IRequiresSessionState, sinon la session ne sera pas disponible (= null). Le gestionnaire peut bien sûr aussi renvoyer un objet sérialisé JSON si certaines données doivent être renvoyées au JavaScript appelant.

Rendu disponible par web.config :

<httpHandlers>
    <add verb="GET,HEAD" path="SessionHeartbeat.ashx" validate="false" type="SessionHeartbeatHttpHandler"/>
</httpHandlers>

ajouté de balexandre le 14 août 2012

J'ai tellement aimé cet exemple que je veux améliorer le HTML/CSS et la partie rythmique.

changer ceci

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

en

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

et ajouter

// 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 et CSS

<div class="heartbeat">&hearts;</div>

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

voici un exemple concret pour seulement la partie qui bat : http://jsbin.com/ibagob/1/

0 votes

@veggerby "à un gestionnaire HTTP factice qui ne fait rien d'autre que de maintenir ma session en vie". Pouvez-vous s'il vous plaît poster un exemple de code de HTTP Handler pour garder la session en vie ?

0 votes

Non, et votre seule option (je suppose) est d'augmenter le délai d'attente de la session, mais c'est probablement une mauvaise idée à long terme.

1 votes

Je faisais des recherches sur un problème connexe et je suis tombé sur cette solution. C'est une bonne chose. Une question cependant, si l'utilisateur laisse son navigateur ouvert, et disons que le PC ne se met pas en veille pendant 10 heures, la session sera maintenue en vie aussi longtemps, n'est-ce pas ? Est-ce exact ?

81voto

Maryan Points 121

Si vous utilisez ASP.NET MVC, vous n'avez pas besoin d'un gestionnaire HTTP supplémentaire et de quelques modifications du fichier web.config. Tout ce dont vous avez besoin, c'est d'ajouter une action simple dans un contrôleur Home/Common :

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

écrivez un morceau de code JavaScript comme celui-ci (je l'ai placé dans l'un des fichiers JavaScript du site) :

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()", 5*60*1000);
}

function KeepSessionAlive() {
    if (keepSessionAlive && keepSessionAliveUrl != null) {
        $.ajax({
            type: "POST",
            url: keepSessionAliveUrl,
            success: function () { keepSessionAlive = false; }
        });
    }
    CheckToKeepSessionAlive();
}

et initialiser cette fonctionnalité en appelant une fonction JavaScript :

SetupSessionUpdater('/Home/KeepSessionAlive');

Veuillez noter ! J'ai mis en œuvre cette fonctionnalité uniquement pour les utilisateurs autorisés (il n'y a aucune raison de conserver l'état de la session pour les invités dans la plupart des cas) et la décision de conserver l'état de la session active n'est pas seulement basée sur - le navigateur est-il ouvert ou non, mais l'utilisateur autorisé doit faire une certaine activité sur le site (déplacer une souris ou taper une touche).

3 votes

Pour MVC, je pense que c'est la meilleure réponse. Pas besoin d'utiliser le fichier .ashx, pourquoi le feriez-vous ?

0 votes

Avec Gestionnaire HTTP dans asp mvc vérifier ce J'espère que cela aidera quelqu'un.

4 votes

Maryan, vous pouvez aussi utiliser @Url.Action("KeepSessionAlive","Home") dans la fonction d'initialisation afin de ne pas avoir à coder en dur l'URL et de lancer le premier bloc à l'intérieur d'un IIFE et d'exporter simplement l'adresse de l'utilisateur. SetupSessionUpdater puisque c'est la seule chose qui doit être invoquée en externe - quelque chose comme ceci : SessionUpdater.js

11voto

BornToCode Points 887

Chaque fois que vous faites une demande au serveur, le délai d'attente de la session est réinitialisé. Vous pouvez donc simplement faire un appel ajax à un gestionnaire HTTP vide sur le serveur, mais assurez-vous que le cache du gestionnaire est désactivé, sinon le navigateur mettra votre gestionnaire en cache et ne fera pas de nouvelle demande.

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 - Il n'est pas nécessaire de stocker les variables dans la session. Il suffit de préformer une requête au serveur.

2voto

Henry Troup Points 107

Avez-vous vraiment besoin de conserver la session (avez-vous des données dans celle-ci ?) ou suffit-il de simuler cela en réinstançant la session lorsqu'une requête arrive ? Dans le premier cas, utilisez la méthode ci-dessus. Dans le second cas, essayez quelque chose comme l'utilisation du gestionnaire d'événement Session_End.

Si vous avez l'authentification par formulaire, vous obtenez quelque chose dans Global.asax.cs comme

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);
    ...
     }

Et vous fixez la durée de vie du ticket bien plus longue que celle de la session. Si vous ne vous authentifiez pas, ou si vous utilisez une méthode d'authentification différente, il existe des astuces similaires. L'interface web de Microsoft TFS et SharePoint semblent les utiliser - l'indice est que si vous cliquez sur un lien sur une page périmée, vous obtenez des invites d'authentification dans la fenêtre popup, mais si vous utilisez simplement une commande, cela fonctionne.

0voto

Peter Points 9636

Voici une solution alternative qui devrait survivre si le PC client se met en mode veille.

Si vous avez un grand nombre d'utilisateurs connectés, utilisez cette option avec précaution car elle peut consommer beaucoup de mémoire du serveur.

Après la connexion (je fais cela dans l'événement LoggedIn du contrôle de connexion)

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)

0 votes

Pourquoi cet article a-t-il été rejeté ? Y a-t-il un problème que je n'ai pas mentionné ? Si c'est le cas, partagez-le avec les autres lecteurs pour qu'ils en soient informés !

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X