【问题标题】:ASP.NET Session fails to renew itselfASP.NET 会话无法自行更新
【发布时间】:2013-12-06 14:45:38
【问题描述】:

我的任务是向 ASP.NET 4.0 Web 窗体应用程序添加功能,以便在用户会话结束前不久警告用户,并提供继续会话或结束会话的选项。

我已经通过一个确认对话框实现了这一点,该对话框警告用户会话即将结束,并提供按“确定”继续会话或按“取消”结束会话的选项。

按“取消”后,页面将重定向到注销页面。

按下“确定”后,我在应用程序 (KeepAlive.aspx) 的空 ASPX 页面上调用 JQuery GET 请求。据我了解,当用户向页面发出请求时,ASP.NET 应该负责更新会话 - 从而重置会话超时。

但是,我发现当用户按下 OK 时,会话没有延长,所以它超时了。尽管 GET 请求显然是成功的(例如调用了回调函数)。

我用来实现此功能的代码以 JavaScript 函数的形式存在,该函数通过母版页上的 onload 事件调用 - 因此它被应用程序中的所有其他页面继承。

var intervalID;

/* Set a timeout interval based on the server timeout value (-10%) */
function setTimeoutInterval() 
{
    /* Session timeout warning dialog */

    // Get session timeout value
    var timeoutMins = "<asp:ContentPlaceHolder id='timeoutPlaceholder' runat='server'><%= Session.Timeout %></asp:ContentPlaceHolder>";

    // Subtract 10% of the timeout value - to give the user a chance to continue the session before it expires
    var remainingTimeMins = Math.ceil(timeoutMins * 0.1);
    var timeoutMins = timeoutMins * 0.9;

    // Convert the timeout value to milliseconds
    var timeout = timeoutMins * 60 * 1000;

    // Set javascript timeout
    intervalID = window.setInterval("displayTimeoutDialog(" + remainingTimeMins + ")", timeout);
}

/* Display a dialog prompting the user to continue the current session or to end the session */
function displayTimeoutDialog(remainingTimeMins) 
{
    var result = confirm("The session will end in ~" + remainingTimeMins +
    " minute(s). Press OK to continue, or Cancel to log out.");

    if (result == true) {
        // Keep the session alive
        alert("Keep alive!");
        $.get("KeepAlive.aspx", function() { alert("Successful request"); });
    }
    else {
        // Redirect to the logout page
        window.location.href("Logout.aspx");
    }
}

【问题讨论】:

  • 为什么要将 JavaScript 变量设置为 asp 服务器控件...然后将其乘以 .9?
  • @Mike 他没有将其设置为服务器控件。他的代码将呈现为:“var timeoutMins = 20”或任何设置。然后他将其乘以 0.9,以便在会话实际到期之前弹出对话框。
  • 是的,cmets 解释了它。我只是从服务器获取服务器超时值(例如 20 分钟),然后设置一个间隔以在会话到期之前警告用户(20 * 0.9 = 18 分钟,因此警告将在会话前 2 分钟变为过期)。
  • @Stefan 我知道 ASP.NET 会在它到达页面之前处理它......这只是一种令人困惑的方式,并且有更简单的方法来获取服务器变量javascript。
  • 另一种选择是使用文字: 并在代码隐藏中设置其值。

标签: javascript jquery asp.net session-timeout


【解决方案1】:

我想知道 AJAX GET 是否还不够。可能是 GET 不会触发整个 Page 生命周期,因此不会更新会话。您是否尝试过重新加载页面而不仅仅是发出 GET?我知道它没有那么优雅,但知道会很有趣。

【讨论】:

  • 重新加载当前页面肯定会起作用,但我不能这样做,因为用户会丢失他们所做的更改。我看到了另一个 StackOverflow 用户向我建议的 GET 请求的想法,但也许他们没有测试他们的解决方案。
  • 是的,我以为他们会丢失更改...您是否查看过有关会话 ID 的其他答案?要尝试的另一件事是确保 AJAX 请求未使用“$.ajaxSetup({cache:false})”进行缓存。最后,这似乎是一个与您的问题相关的好问题:stackoverflow.com/questions/9374190/…
  • 关闭缓存并没有解决问题。现在检查相关问题...
【解决方案2】:

我们找到了一个不需要刷新用户所在页面的解决方案。

这是使用页面上隐藏的 HTML iframe 实现的:

<iframe id="keepAlive" src="KeepAlive.aspx" frameborder="0" width="0" height="0" runat="server"></iframe>

我将实现计时器和对话框的 javascript 方法添加到 iframe 页面。当用户想要更新会话时,他们按对话框按钮上的“继续”,然后我们只需刷新 iframe 页面。刷新会导致服务器更新会话,而用户不会丢失他们正在处理的页面 - 因为刷新的是 iframe,而不是用户所在的实际页面。

请记住,所有这些代码都位于 ASP.NET 母版页中,因此它在我们应用程序的每个 ASPX 页面上都被继承。 iFrame 上的 Javascript 在主体 onload 事件中被调用。

        var intervalID;

        /* Set a timeout interval based on the server timeout value (-10%) */
        function setTimeoutInterval() 
        {
            /* Session timeout warning dialog */

            // Get session timeout value
            var timeoutMins = "<%= Session.Timeout %>";

            // Subtract 10% of the timeout value - to give the user a chance to continue the session before it expires
            var remainingTimeMins = Math.ceil(timeoutMins * 0.1);
            var timeoutMins = timeoutMins * 0.9;

            // Convert the timeout value to milliseconds
            var timeout = timeoutMins * 60 * 1000;

            // Set javascript timeout
            intervalID = window.setInterval("displayTimeoutDialog(" + remainingTimeMins + ")", timeout);
        }

        /* Display a dialog prompting the user to continue the current session or to end the session */
        function displayTimeoutDialog(remainingTimeMins) 
        {
            var result = confirm("The session will end in ~" + remainingTimeMins +
            " minute(s). Press OK to renew, or Cancel to let your session expire.");

            if (result == true) {
                // Keep the session alive and clear the interval
                alert("Session renewed.");
                window.location.href("KeepAlive.aspx");
            }
            else {
                // Redirect to the logout page
                window.clearInterval(intervalID);
            }

        }

【讨论】:

    【解决方案3】:

    确保您的请求包含相同的会话 ID,并且您没有使用无 Cookie 会话 ID。

    http://msdn.microsoft.com/en-us/library/ms178581%28v=vs.90%29.aspx

    会话标识符

    会话由一个唯一标识符标识,该标识符可由以下人员读取 使用 SessionID 属性。当会话状态为 ASP.NET 应用程序,对应用程序中一个页面的每个请求都是 检查从浏览器发送的 SessionID 值。如果没有 SessionID 提供值,ASP.NET 启动一个新会话和 SessionID 该会话的值与响应一起发送到浏览器。

    默认情况下,SessionID 值存储在 cookie 中。但是,您可以 还将应用程序配置为在 URL 中存储 SessionID 值 用于“无 cookie”会话。

    只要继续发出请求,会话就会被视为处于活动状态 具有相同的 SessionID 值。如果请求之间的时间 特定会话超过指定的超时值(以分钟为单位), 会话被视为过期。过期的请求 SessionID 值产生一个新的会话。

    【讨论】:

    • 来自 web.config 文件:cookieless="false"。如何确保请求包含相同的会话 ID?为什么会话处于活动状态时会话 ID 会更改?
    • 我的猜测是 AJAX get 没有在请求中发送会话 ID。您可以查看服务器端页面上的传入请求,KeepAlive.aspx 的 Page_load 事件,并查看 Page.Request.Cookies 集合中是否包含 ASP.NET_SessionId。如果它没有正确的 ID,那么您将获得一个新会话。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-04
    • 2011-02-08
    • 2011-10-21
    • 2011-02-13
    • 1970-01-01
    • 2010-11-23
    相关资源
    最近更新 更多