【问题标题】:Session Timeout Warning in ASP.NETASP.NET 中的会话超时警告
【发布时间】:2012-05-18 08:17:46
【问题描述】:

我有一个 asp.net 站点,我需要在会话超时(比如说 10 分钟)时发生弹出/层/警报。弹出窗口会说您的帐户会话将由于不活动而过期,并有一个继续会话按钮或一个注销按钮。

我在网上看到了不同的方法,但最好/正确的方法是什么?如果弹出窗口打开的时间过长,我是否必须设置额外的超时时间?

【问题讨论】:

    标签: c# asp.net .net session iis


    【解决方案1】:
    <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>
    

    【讨论】:

    • 我在我的 Web.config 文件中添加了&lt;sessionState mode="StateServer" cookieless="false" timeout="180"&gt;&lt;/sessionState&gt;。如何分配var sessionTimeoutWarnin
    • 实现这种客户端代码可能会引发安全漏洞问题?
    • @FerR 您在考虑什么安全问题?您是否担心“
    • @JeffMergler 我的 QSA 区域鼓励我们(开发团队)避免使用 Javascript 或任何客户端脚本来执行操作。我们的网络应用程序是银行核心的一部分,因此必须满足强大的测试周期。例如,我担心攻击者是否可以更改或将恶意代码注入客户端脚本并扩展任意会话。 "
    【解决方案2】:

    您可以做的是使用一些 javascript 来触发消息。使用计时器在一段时间后触发(在您的应用程序中为会话超时设置的时间段 - 几分钟)。

    在那段时间之后,向用户显示会话将超时的确认对话框。如果用户点击保持会话。在页面中进行虚拟回发,以免会话丢失。您还可以进行 AJAX 调用,这样用户就不会看到页面重新加载并丢失输入数据。

    【讨论】:

      【解决方案3】:

      我去看了Pranay Ranapost的文章,总体思路我喜欢,但是代码可以使用一些精简。所以这是我的版本。对于平板电脑/移动设备问题,请参见下文:

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

      【讨论】:

        【解决方案4】:

        下面是一些带有 jQ​​uery 的 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);
            }
        

        【讨论】:

          【解决方案5】:

          如果使用滑动过期,您可以使用 jquery 和 setinterval 函数在后台执行 Ajax 发布以刷新超时,或者通过记录会话开始时间并减去过期时间来获取剩余时间的值。

          【讨论】:

            【解决方案6】:

            您必须在此处使用客户端技术 (javascript)。例如,您将使用 javascript 超时工具,然后显示警告。如果用户单击确定,您可能需要做一些事情来保持会话处于活动状态。我建议使用 jquery.ajax 方法,并调用服务器,可以是一个虚拟调用 - 只是为了保持会话活动。

            【讨论】:

              【解决方案7】:

              这个问题之前已经解决过,例如 ASP.NET - Javascript timeOut Warning based on sessionState timeOut in web.config

              但是,AFAIK 没有完全可靠的方法来做到这一点,因为:

              • 如果用户使用同一会话打开了多个窗口,则一个窗口可能比另一个窗口更新,并且最旧窗口上的客户端会话超时将是陈旧的/不正确的。
              • 如果您往返于服务器以查看当前会话到期时间,您将延长它,从而破坏弹出/警报的目的。

              【讨论】:

              • 你能告诉我,如何在 MVC 4 中提醒用户会话超时?另外我没有使用表单身份验证。没有表单认证可以吗?
              猜你喜欢
              • 2016-09-11
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-02-06
              • 2012-07-17
              • 1970-01-01
              • 2014-07-18
              • 1970-01-01
              相关资源
              最近更新 更多