ASP.NET中的会话超时警告

16
我有一个asp.net网站,当会话超时(比如10分钟)时,我需要一个弹出层/提示框。弹出层会显示您的帐户会话因为不活动而将要过期,并提供继续会话或注销的选项。 我在网上看到了不同的方法来处理这个问题,但什么是最好/适当的方法?如果弹出层打开时间太长,我是否需要设置额外的超时时间?
7个回答

27
<script type="text/javascript">
    var sessionTimeoutWarning = "<%= System.Configuration.ConfigurationManager.AppSettings["SessionWarning"].ToString()%>";
        var sessionTimeout = "<%= Session.Timeout %>";

    var sTimeout = parseInt(sessionTimeoutWarning) * 60 * 1000;
    setTimeout('SessionWarning()', sTimeout);

    function SessionWarning() {
        var message = "Your session will expire in another " +
            (parseInt(sessionTimeout) - parseInt(sessionTimeoutWarning)) +
            " mins! Please Save the data before the session expires";
        alert(message);
    }
</script>

1
我在Web.config文件中添加了<sessionState mode="StateServer" cookieless="false" timeout="180"></sessionState>。如何分配var sessionTimeoutWarning - SearchForKnowledge
实现这种客户端代码可能会带来安全漏洞问题吗? - Fer R
@FerR 你在考虑什么安全问题?你担心 "<%=" 引用的问题吗? - Jeff Mergler
1
@JeffMergler 我们的 QSA 部门鼓励我们(开发团队)避免使用 JavaScript 或任何客户端脚本来执行操作。我们的 Web 应用程序是银行核心的一部分,因此必须符合严格的测试周期。我的担忧是,例如,如果攻击者可以更改或注入恶意代码到客户端脚本并扩展任意会话,则“<%=”是潜在的漏洞。 - Fer R

7
这个问题以前已经有人提出过,比如ASP.NET - 基于web.config中sessionState timeOut的Javascript超时警告。但是,据我所知,没有一种完全可靠的方法来解决这个问题,因为:
  • 如果用户打开了多个使用同一会话的窗口,则其中一个窗口可能比另一个窗口更新,而最旧的窗口上的客户端会话超时将过时/不正确。
  • 如果您往返于服务器以查看当前会话到期时间,则会延长它,从而使弹出/警报失去意义。

请问如何在MVC 4中向用户发出会话超时警告?另外,我没有使用表单身份验证。是否可以在没有表单身份验证的情况下实现? - Huma Ali

3

我看了Pranay Rana文章,觉得总体思路不错,但是代码需要精简优化。这是我的版本。如需查看平板电脑/移动设备问题,请参见以下内容:

<script language="javascript" type="text/javascript">
    var minutesForWarning = 4;
    var sessionTimeout = parseInt("@Session.Timeout"); // razor syntax, otherwise use <%= Session.Timeout %>
    var showWarning = true;

    function SessionWarning() {
        showWarning = false;
        alert("Your session will expire in " + minutesForWarning + " mins! Please refresh page to continue working.");
        // leave a second for redirection fct to be called if expired in the meantime
        setTimeout(function () { showWarning = true; }, 1000);
    }

    function RedirectToWelcomePage() {
        if (showWarning)
            alert("Session expired. You will be redirected to welcome page.");
        document.getElementById('logoutForm').submit();
        // window.location = "../Welcome.aspx"; // alternatively use window.location to change page
    }

    setTimeout('SessionWarning()', (sessionTimeout - minutesForWarning) * 60 * 1000);
    setTimeout('RedirectToWelcomePage()', sessionTimeout * 60 * 1000);
</script>

在平板电脑或移动设备上,您不能依赖setTimeout,因为当设备被锁定或浏览器不活动时,JavaScript执行会被暂停。相反,我正在进行定期检查(在我的情况下,我认为每10秒足够):

<script language="javascript" type="text/javascript">
    function addMinutes(date, minutes) {
        return new Date(date.getTime() + minutes * 60 * 1000);
    }
    function remainingMinutes(date) {
        return Math.round((date - (new Date()).getTime()) / 60 / 1000);
    }

    var minutesForWarning = 5;
    var sessionTimeout = parseInt("@Session.Timeout");
    var showWarning = true;
    var showRedirect = true;
    var timeToWarn = addMinutes(new Date(), sessionTimeout - minutesForWarning);
    var timeToEnd = addMinutes(new Date(), sessionTimeout);

    function CheckTime() {
        if (showWarning && new Date() > timeToWarn && new Date() < timeToEnd) {
            showRedirect = false;
            showWarning = false;
            alert("Your session will expire in " + remainingMinutes(timeToEnd)) + " mins! Please refresh page to continue working.");
        }
        if (new Date() > timeToEnd) {
            if (showRedirect)
                alert("Session expired. You will be redirected to welcome page ");
            document.getElementById('logoutForm').submit();
            // window.location = "../Welcome.aspx"; // alternatively use window.location to change page
        }
        if (showRedirect == false)
            showRedirect = true;
    }

    setInterval(CheckTime, 10000);

</script>

1
以下是一些带有jQuery的JavaScript代码,用于警告用户关于ASP.NET表单身份验证超时,并在超时时重定向到登录页面。它可以改进和适应会话超时。每当用户通过点击、键入或调整大小与页面交互时,它也会通过“ping”服务器来重置身份验证超时。请注意,这确实会增加服务器的负载,因为每次点击、按键、调整大小都会进行“ping”。但这很小。如果您有很多用户在打字,您需要评估影响。我想不出另一种方法来做这件事,因为服务器必须参与其中,因为超时是在那里过期的。另请注意,超时没有硬编码在JS中。它从服务器获取超时时间,因此您只需要在Web.config中维护它一个地方即可。
(function ($, undefined) {

    if (!window.session) {

        window.session = {

            monitorAuthenticationTimeout: function (redirectUrl, pingUrl, warningDuration, cushion) {

                // If params not specified, use defaults.
                redirectUrl = redirectUrl || "~/Account/Login";
                pingUrl = pingUrl || "~/Account/Ping";
                warningDuration = warningDuration || 45000;
                cushion = cushion || 4000;

                var timeoutStartTime,
                    timeout,
                    timer,
                    popup,
                    countdown,
                    pinging;

                var updateCountDown = function () {
                    var secondsRemaining = Math.floor((timeout - ((new Date()).getTime() - timeoutStartTime)) / 1000),
                        min = Math.floor(secondsRemaining / 60),
                        sec = secondsRemaining % 60;

                    countdown.text((min > 0 ? min + ":" : "") + (sec < 10 ? "0" + sec : sec));

                    // If timeout hasn't expired, continue countdown.
                    if (secondsRemaining > 0) {
                        timer = window.setTimeout(updateCountDown, 1000);

                    }
                    // Else redirect to login.
                    else {
                        window.location = redirectUrl;
                    }
                };

                var showWarning = function () {
                    if (!popup) {
                        popup = $(
                            "<div style=\"text-align:center; padding:2em; color: black; font-color: black; background-color:white; border:2px solid red; position:absolute; left: 50%; top:50%; width:300px; height:120px; margin-left:-150px; margin-top:-90px\">" +
                                "<span style=\"font-size:1.4em; font-weight:bold;\">INACTIVITY ALERT!</span><br/><br/>" +
                                "You will be automatically logged off.<br/><br/>" +
                                "<span style=\"font-size:1.4em; font-weight:bold;\" id=\"countDown\"></span><br/><br/>" +
                                "Click anywhere on the page to continue working." +
                            "</div>")
                            .appendTo($("body"));

                        countdown = popup.find("#countDown");
                    }

                    popup.show();
                    updateCountDown();
                };

                var resetTimeout = function () {
                    // Reset timeout by "pinging" server.
                    if (!pinging) {
                        pinging = true;
                        var pingTime = (new Date()).getTime();
                        $.ajax({
                            type: "GET",
                            dataType: "json",
                            url: pingUrl,
                        }).success(function (result) {

                            // Stop countdown.
                            window.clearTimeout(timer);
                            if (popup) {
                                popup.hide();
                            }

                            // Subract time it took to do the ping from
                            // the returned timeout and a little bit of 
                            // cushion so that client will be logged out 
                            // just before timeout has expired.
                            timeoutStartTime = (new Date()).getTime();
                            timeout = result.timeout - (timeoutStartTime - pingTime) - cushion;

                            // Start warning timer.
                            timer = window.setTimeout(showWarning, timeout - warningDuration);
                            pinging = false;
                        });
                    }
                };

                // If user interacts with browser, reset timeout.
                $(document).on("mousedown mouseup keydown keyup", "", resetTimeout);
                $(window).resize(resetTimeout);

                // Start fresh by reseting timeout.
                resetTimeout();
            },
        };
    }

})(jQuery);

只需在页面加载时调用上述代码:
window.session.monitorAuthenticationTimeout(
        "/Account/Login",    // You could also use "@FormsAuthentication.LoginUrl" in Razor.
        "/Account/Ping");

在服务器端,您需要一个返回剩余时间的操作。您也可以添加更多信息。
    public JsonResult Ping()
    {
        return Json(new { 
                        timeout = FormsAuthentication.Timeout.TotalMilliseconds 
                    }, 
                    JsonRequestBehavior.AllowGet);
    }

0
你需要使用客户端技术(JavaScript)在这里进行操作。例如,您可以使用 JavaScript 超时设施来显示警告。如果用户单击“确定”,则可以执行某些操作以保持会话活动状态。我建议使用 jQuery.ajax 方法,并向服务器发出调用,可以是虚拟调用 - 只需保持会话活动即可。

0
你可以使用jQuery和setInterval函数,在后台执行Ajax post来刷新超时时间(如果使用滑动过期),或者通过记录会话开始时间并从过期时间中减去来获取剩余时间的值。

0
你可以使用一些Javascript来触发这个消息。使用计时器在一定的时间后触发消息(时间设置为应用程序中的会话超时时间-几分钟)。
在此期间,向用户显示一个确认对话框,告知会话将要超时。如果用户点击保持会话,则在页面上进行虚拟PostBack,以便不会丢失会话。您还可以进行AJAX调用,以便用户不会看到页面重新加载并且输入数据丢失。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接