Сохранение сеанса ASP.NET открытым / живым - PullRequest
107 голосов
/ 16 сентября 2009

Какой самый простой и ненавязчивый способ сохранить сеанс ASP.NET, пока у пользователя открыто окно браузера? Это приурочено AJAX звонки? Я хочу предотвратить следующее: иногда пользователи долго держат свое окно открытым, затем вводят данные, и при отправке ничего не работает, потому что сеанс на стороне сервера истек. Я не хочу увеличивать значение тайм-аута на сервере более 10 минут, поскольку я хочу, чтобы закрытые сеансы (закрывая окно браузера) быстро истекали.

Предложения, примеры кода?

Ответы [ 8 ]

166 голосов
/ 16 сентября 2009

Я использую JQuery для выполнения простого AJAX-вызова фиктивного обработчика HTTP, который ничего не делает, кроме как поддерживает мой сеанс:

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

Обработчик сеанса может быть простым:

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

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

Ключ должен добавить IRequiresSessionState, в противном случае Session будет недоступен (= ноль). Конечно, обработчик также может возвращать сериализованный объект JSON, если некоторые данные должны быть возвращены вызывающему JavaScript.

Доступно через web.config:

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

добавлено из balexandre 14 августа 2012 г.

Мне очень понравился этот пример, и я хочу улучшить его с помощью HTML / CSS и ритма

изменить это

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

в

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

и добавьте

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

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

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

Вот живой пример только для бьющейся части: http://jsbin.com/ibagob/1/

61 голосов
/ 07 января 2013

Если вы используете ASP.NET MVC - вам не нужен дополнительный обработчик HTTP и некоторые модификации файла web.config. Все, что вам нужно - просто добавить простое действие в контроллер Home / Common:

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

, напишите фрагмент кода JavaScript, подобный этому (я поместил его в один из файлов JavaScript сайта):

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

и инициализируйте эту функцию, вызвав функцию JavaScript:

SetupSessionUpdater('/Home/KeepSessionAlive');

Обратите внимание! Я реализовал эту функцию только для авторизованных пользователей (в большинстве случаев нет оснований сохранять состояние сеанса для гостей), и решение поддерживать состояние сеанса не только на основе - is браузер открыт или нет, но авторизованный пользователь должен выполнить некоторые действия на сайте (переместить мышь или ввести какую-нибудь клавишу).

7 голосов
/ 21 октября 2013

Всякий раз, когда вы делаете запрос к серверу, время ожидания сеанса сбрасывается. Таким образом, вы можете просто выполнить ajax-вызов пустого обработчика HTTP на сервере, но убедитесь, что кэш обработчика отключен, в противном случае браузер кэширует ваш обработчик и не будет делать новый запрос.

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 - Нет необходимости в хранении переменных в сеансе. Достаточно просто выполнить запрос к серверу.

2 голосов
/ 05 мая 2016

Вы можете просто написать этот код в своем файле сценария Java, вот и все.

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

1140000 - это время обновления, оно обновит время ожидания сеанса. Время ожидания обновления рассчитывается как время по умолчанию из iis = 20 минут, что означает 20 × 60000 = 1200000 миллисекунд - 60000 миллисекунд (за одну минуту до истечения сеанса) составляет 1140000.

2 голосов
/ 16 сентября 2009

Вам действительно нужно сохранить сеанс (у вас есть данные в нем?), Или этого достаточно, чтобы подделать это путем повторного создания сеанса при поступлении запроса? Если первое, используйте метод выше. Если второе, попробуйте что-то вроде использования обработчика событий Session_End.

Если у вас есть Аутентификация с помощью форм, то вы получите что-то в 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);
    ...
     }

И вы устанавливаете время жизни билета намного дольше, чем время жизни сеанса. Если вы не проходите аутентификацию или используете другой метод аутентификации, есть похожие приемы. Веб-интерфейс Microsoft TFS и SharePoint, кажется, используют их - выгода в том, что если вы щелкнете по ссылке на устаревшей странице, вы получите запрос аутентификации во всплывающем окне, но если вы просто используете команду, она работает.

0 голосов
/ 02 января 2017

Здесь плагин JQuery версии решения Maryan с оптимизацией дескриптора. Только с 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)

и как он импортирует в ваш * .cshtml

$('body').heartbeat(); // Simple
$('body').heartbeat({url:'@Url.Action("Home", "heartbeat")'}); // different url
$('body').heartbeat({every:400000}); // different timeout
0 голосов
/ 12 октября 2016

Я потратил несколько дней, пытаясь выяснить, как продлить сеанс пользователей в WebForms через всплывающее диалоговое окно, дающее пользователю возможность продлить сеанс или разрешить его истечение. Главное, что вам нужно знать, это то, что вам не нужны какие-либо из этих причудливых «HttpContext» вещей, которые встречаются в некоторых других ответах. Все, что вам нужно, это jQuery's $ .post (); метод. Например, при отладке я использовал:

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

и на вашем сайте вы бы использовали что-то вроде:

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

Это так просто. Кроме того, если вы хотите предложить пользователю возможность обновить сеанс, сделайте что-то похожее на следующее:

    <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>

Не забудьте добавить диалог в ваш 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 голосов
/ 03 июня 2014

Вот альтернативное решение, которое должно выжить, если клиентский компьютер перейдет в спящий режим.

Если у вас есть огромное количество зарегистрированных пользователей, используйте это осторожно, так как это может съесть много памяти сервера.

После входа в систему (я делаю это в событии LoggedIn элемента управления входом в систему)

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)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...