Prowadzenie ASP.NET sesja Otwarta / żywa

Który jest najprostszym i najbardziej dyskretnym sposobem na utrzymanie ASP.NET session alive tak długo, jak długo użytkownik ma otwarte okno przeglądarki? Czy to timed AJAX połączenia? Chcę zapobiec następującej sytuacji: czasami użytkownicy zachowują swoje okno otwarte przez długi czas, następnie wpisują rzeczy, a przy wysyłaniu nic już nie działa, ponieważ sesja po stronie serwera wygasła. Nie chcę zwiększać wartości timeout na więcej niż 10 min na serwerze, ponieważ chcę zamknięte sesje (przez zamknięcie okna przeglądarki) do time out szybko.

Sugestie, próbki kodu?

Author: Luis Gouveia, 2009-09-16

8 answers

Używam JQuery do wykonywania prostego wywołania AJAX do atrapy obsługi HTTP, który nie robi nic poza utrzymaniem sesji przy życiu:

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

Obsługa sesji może być tak prosta jak:

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

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

Kluczem jest dodanie IRequiresSessionState, w przeciwnym razie sesja nie będzie dostępna (=null). Obsługa może oczywiście również zwrócić obiekt serializowany JSON, jeśli niektóre dane powinny być zwrócone do wywołującego JavaScript.

[[7]}udostępniane przez WWW.config:
<httpHandlers>
    <add verb="GET,HEAD" path="SessionHeartbeat.ashx" validate="false" type="SessionHeartbeatHttpHandler"/>
</httpHandlers>

Dodany z balexandre on August 14th, 2012

Tak bardzo spodobał mi się ten przykład, że chcę poprawić z HTML / CSS i częścią beat

Zmień to

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

Do

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

I dodać

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

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

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

Oto przykład na żywo tylko dla części bijącej: http://jsbin.com/ibagob/1/

 161
Author: veggerby,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:01

Jeśli używasz ASP.NET MVC – nie potrzebujesz dodatkowej obsługi HTTP i niektórych modyfikacji www.plik konfiguracyjny. Wszystko – czego potrzebujesz-wystarczy dodać kilka prostych czynności w kontrolerze Home/Common:

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

, Napisz fragment kodu JavaScript, taki jak ten (umieściłem go w jednym z plików JavaScript strony):

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

, i zainicjalizuj tę funkcjonalność, wywołując funkcję JavaScript:

SetupSessionUpdater('/Home/KeepSessionAlive');

Uwaga! zaimplementowałem tę funkcjonalność tylko dla autoryzowani użytkownicy (nie ma powodu, aby utrzymać stan sesji dla gości w większości przypadków), a decyzja o utrzymaniu stanu sesji jest nie tylko na podstawie-czy przeglądarka jest otwarta, czy nie, ale upoważniony użytkownik musi wykonać pewną aktywność na stronie (poruszyć myszką lub wpisać jakiś klawisz).

 53
Author: Maryan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-07 12:23:16

Za każdym razem, gdy składasz żądanie do serwera, limit czasu sesji resetuje się. Możesz więc po prostu wykonać wywołanie ajax do pustego modułu obsługi HTTP na serwerze, ale upewnij się, że pamięć podręczna tego modułu jest wyłączona, w przeciwnym razie przeglądarka będzie buforować Twój moduł obsługi i nie będzie wysyłać nowego żądania.

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-nie ma potrzeby narzutu przechowywania zmiennych w sesji. Wystarczy tylko preformowanie żądania do serwera.

 6
Author: BornToCode,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-21 09:15:43

Czy naprawdę musisz zachować sesję (czy masz w niej dane?) a może wystarczy to sfałszować, wznawiając sesję, gdy pojawi się prośba? Jeśli pierwszy, użyj metody powyżej. Jeśli drugi, spróbuj czegoś takiego jak użycie obsługi zdarzenia Session_End.

Jeśli masz uwierzytelnianie formularzy, dostajesz coś w globalnym.asax.cs jak

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

I ustawiasz żywotność biletu znacznie dłużej niż żywotność sesji. Jeśli nie uwierzytelniasz lub używasz inna metoda uwierzytelniania, istnieją podobne sztuczki. Microsoft TFS web interface i SharePoint wydają się używać tych-rozdawać jest to, że jeśli klikniesz link na starej stronie, otrzymasz monity uwierzytelniania w wyskakującym oknie, ale jeśli po prostu użyć polecenia, to działa.

 2
Author: Henry Troup,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-16 16:20:28

Możesz po prostu napisać ten kod w swoim pliku java script.

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

1140000 jest czasem odświeżania, odświeży czas sesji. Limit czasu odświeżania jest obliczany jako domyślny czas poza iis = 20 minut, czyli 20 × 60000 = 1200000 milisekund - 60000 milisekund (jedna minuta przed wygaśnięciem sesji ) wynosi 1140000.

 2
Author: ANKIT KISHOR,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-05 06:53:37

Oto alternatywne rozwiązanie, które powinno przetrwać, jeśli komputer kliencki przejdzie w tryb uśpienia.

Jeśli masz ogromną ilość zalogowanych użytkowników, używaj tego ostrożnie, ponieważ może to pochłonąć dużo pamięci serwera.

Po zalogowaniu (robię to w zdarzeniu LoggedIn kontroli logowania)

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
Author: Peter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-29 20:22:29

Spędziłem kilka dni próbując dowiedzieć się, jak przedłużyć sesję użytkownika w formularzach internetowych za pomocą wyskakującego okna dialogowego dającego użytkownikowi możliwość odnowienia sesji lub umożliwienia jej wygaśnięcia. # 1 rzeczą, którą musisz wiedzieć, jest to, że nie potrzebujesz żadnej z tych fantazyjnych rzeczy "HttpContext", które dzieją się w niektórych innych odpowiedziach. Wszystko czego potrzebujesz to $jQuery.post (); metoda. Na przykład podczas debugowania użyłem:

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

A na swojej stronie używasz czegoś takiego:

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

It ' s as easy tak. Ponadto, jeśli chcesz poprosić Użytkownika o opcję odnowienia sesji, zrób coś podobnego do następującego:

    <script type="text/javascript">
    $(function () { 
        var t = 9;
        var prolongBool = false;
        var originURL = document.location.origin;
        var expireTime = <%= FormsAuthentication.Timeout.TotalMinutes %>;

        // Dialog Counter
        var dialogCounter = function() {
            setTimeout( function() {
                $('#tickVar').text(t);
                    t--;
                    if(t <= 0 && prolongBool == false) {
                        var originURL = document.location.origin;
                        window.location.replace(originURL + "/timeout.aspx");
                        return;
                    }
                    else if(t <= 0) {
                        return;
                    }
                    dialogCounter();
            }, 1000);
        }

        var refreshDialogTimer = function() {
            setTimeout(function() { 
                $('#timeoutDialog').dialog('open');
            }, (expireTime * 1000 * 60 - (10 * 1000)) );
        };

        refreshDialogTimer();

        $('#timeoutDialog').dialog({
            title: "Session Expiring!",
            autoOpen: false,
            height: 170,
            width: 350,
            modal: true,
            buttons: {
                'Yes': function () {
                    prolongBool = true;
                    $.post("http://localhost:5562/Members/Location/Default.aspx"); 
                    refreshDialogTimer();
                    $(this).dialog("close");
                },
                Cancel: function () {
                    var originURL = document.location.origin;
                    window.location.replace(originURL + "/timeout.aspx");
                }
            },
            open: function() {
                prolongBool = false;
                $('#tickVar').text(10);
                t = 9;
                dialogCounter();
            }
        }); // end timeoutDialog
    }); //End page load
</script>

Nie zapomnij dodać okna dialogowego do swojego html:

        <div id="timeoutDialog" class='modal'>
            <form>
                <fieldset>
                    <label for="timeoutDialog">Your session will expire in</label>
                    <label for="timeoutDialog" id="tickVar">10</label>
                    <label for="timeoutDialog">seconds, would you like to renew your session?</label>
                </fieldset>
            </form>
        </div>
 0
Author: Versatile,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-12 13:58:10

Tutaj wersja wtyczki jQuery rozwiązania Maryan z optymalizacją uchwytów. Tylko z 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)

I jak to robi import w Twoim*.cshtml

$('body').heartbeat(); // Simple
$('body').heartbeat({url:'@Url.Action("Home", "heartbeat")'}); // different url
$('body').heartbeat({every:400000}); // different timeout
 0
Author: AlexPalla,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-02 14:53:09