【问题标题】:Close/kill the session when the browser or tab is closed关闭浏览器或选项卡时关闭/终止会话
【发布时间】:2010-12-27 16:11:47
【问题描述】:

谁能告诉我当用户关闭浏览器时如何关闭/终止会话?我正在为我的 asp.net Web 应用程序使用 stateserver 模式。 onbeforeunload 方法不正确,因为它会在用户刷新页面时触发。

【问题讨论】:

    标签: asp.net session


    【解决方案1】:

    你不能。 HTTP 是一种无状态协议,因此您无法判断用户何时关闭了浏览器,或者他们只是坐在那里,打开浏览器窗口无所事事。

    这就是会话有超时的原因 - 您可以尝试减少超时以更快地关闭非活动会话,但这可能会导致合法用户的会话提前超时。

    【讨论】:

    • facebook 和 gmail 做到了——有人知道他们是如何做到这一点的吗?
    • @NexusRex 您可以设置一个会话cookie,该cookie在浏览器关闭时过期。这不会使会话服务器端过期,但浏览器将不再拥有令牌。
    【解决方案2】:

    如前所述,浏览器不会让服务器知道它何时关闭。

    不过,有一些方法可以实现接近这种行为。您可以放置​​一个小的 AJAX 脚本,在浏览器打开时定期更新服务器。您应该将此与触发用户操作的内容配对,这样您就可以使空闲会话以及已关闭的会话超时。

    【讨论】:

      【解决方案3】:

      正如你所说,当用户单击链接或刷新页面时会触发事件 window.onbeforeunload,因此即使结束会话也不好。

      http://msdn.microsoft.com/en-us/library/ms536907(VS.85).aspx 描述了所有触发 window.onbeforeonload 的情况。 (即)

      但是,您可以在页面上放置一个 JavaScript 全局变量来识别不应触发注销的操作(例如,通过使用来自 onbeforeonload 的 AJAX 调用)。

      下面的脚本依赖于 JQuery

      /*
      * autoLogoff.js
      *
      * Every valid navigation (form submit, click on links) should
      * set this variable to true.
      *
      * If it is left to false the page will try to invalidate the
      * session via an AJAX call
      */
      var validNavigation = false;
      
      /*
      * Invokes the servlet /endSession to invalidate the session.
      * No HTML output is returned
      */
      function endSession() {
         $.get("<whatever url will end your session>");
      }
      
      function wireUpEvents() {
      
        /*
        * For a list of events that triggers onbeforeunload on IE
        * check http://msdn.microsoft.com/en-us/library/ms536907(VS.85).aspx
        */
        window.onbeforeunload = function() {
            if (!validNavigation) {
               endSession();
            }
        }
      
        // Attach the event click for all links in the page
        $("a").bind("click", function() {
           validNavigation = true;
        });
      
        // Attach the event submit for all forms in the page
        $("form").bind("submit", function() {
           validNavigation = true;
        });
      
      }
      
      // Wire up the events as soon as the DOM tree is ready
      $(document).ready(function() {
          wireUpEvents();  
      });
      

      此脚本可能包含在所有页面中

      <script type="text/javascript" src="js/autoLogoff.js"></script>
      

      让我们看一下这段代码:

        var validNavigation = false;
      
        window.onbeforeunload = function() {
            if (!validNavigation) {
               endSession();
            }
        }
      
        // Attach the event click for all links in the page
        $("a").bind("click", function() {
           validNavigation = true;
        });
      
        // Attach the event submit for all forms in the page
        $("form").bind("submit", function() {
           validNavigation = true;
        });
      

      全局变量是在页面级别定义的。如果此变量未设置为 true,则事件 windows.onbeforeonload 将终止会话。

      一个事件处理程序附加到页面中的每个链接和表单以将此变量设置为 true,从而防止在用户只是提交表单或单击链接时终止会话。

      function endSession() {
         $.get("<whatever url will end your session>");
      }
      

      如果用户关闭浏览器/选项卡或导航离开,会话将终止。在这种情况下,全局变量未设置为 true,脚本将对您要结束会话的任何 URL 进行 AJAX 调用

      此解决方案与服务器端技术无关。它没有经过详尽的测试,但在我的测试中似乎运行良好

      【讨论】:

      • 需要注意的是,您必须将其设为同步 Ajax 请求,否则它极不可能被触发。当然,同步 Ajax 请求很丑陋,它们完全占用了浏览器的 UI。
      • @T.J. Crowder:当您的服务器出现问题并且典型响应时间超过 5 秒时,丑陋是轻描淡写 :-)
      • 有效的 cmets。超时时间非常短的同步 AJAX 调用怎么样?请注意,建议的解决方案并非旨在解决孤儿会话的所有问题。它只会覆盖其中的一部分(用户主动关闭浏览器并且注销 URL 响应超快)
      • 如果用户刷新他们的页面或使用浏览器的后退/前进按钮导航后退/前进,这仍然会错误地终止会话。
      • 我建议你添加://this code will handle the F5 or Ctrl+F5 key //need to handle more cases like ctrl+R whose codes are not listed here document.onkeydown = checkKeycode function checkKeycode(e) { var keycode; if (window.event) keycode = window.event.keyCode; else if (e) keycode = e.which; if(keycode == 116) { validNavigation = true; } } like Saravanakumar wrote - 它会阻止刷新时终止会话
      【解决方案4】:

      我是这样做的:

      $(window).bind('unload', function () {
          if(event.clientY < 0) {  
              alert('Thank you for using this app.');
              endSession(); // here you can do what you want ...
          }  
          });
      window.onbeforeunload = function () {
          $(window).unbind('unload');
          //If a string is returned, you automatically ask the 
          //user if he wants to logout or not...
          //return ''; //'beforeunload event'; 
          if (event.clientY < 0) {
              alert('Thank you for using this service.');
              endSession();
          }  
      }  
      

      【讨论】:

      • 如果用户按 ALT+F4 会怎样??
      【解决方案5】:

      当机器因电源故障意外关闭时,无法杀死会话变量。只有当用户长时间空闲或正常注销时才有可能。

      【讨论】:

      • 服务器端,如果你是空闲的或者你的机器是关闭的,它根本没有任何区别。在客户端,您无法控制会话变量。
      【解决方案6】:

      请参考以下步骤:

      1. 首先创建一个页面SessionClear.aspx并编写清除会话的代码
      2. 然后在您的页面或母版页中添加以下 JavaScript 代码:

        <script language="javascript" type="text/javascript">
            var isClose = false;
        
            //this code will handle the F5 or Ctrl+F5 key
            //need to handle more cases like ctrl+R whose codes are not listed here
            document.onkeydown = checkKeycode
            function checkKeycode(e) {
            var keycode;
            if (window.event)
            keycode = window.event.keyCode;
            else if (e)
            keycode = e.which;
            if(keycode == 116)
            {
            isClose = true;
            }
            }
            function somefunction()
            {
            isClose = true;
            }
        
            //<![CDATA[
        
                function bodyUnload() {
        
              if(!isClose)
              {
                      var request = GetRequest();
                      request.open("GET", "SessionClear.aspx", true);
                      request.send();
              }
                }
                function GetRequest() {
                    var request = null;
                    if (window.XMLHttpRequest) {
                        //incase of IE7,FF, Opera and Safari browser
                        request = new XMLHttpRequest();
                    }
                    else {
                        //for old browser like IE 6.x and IE 5.x
                        request = new ActiveXObject('MSXML2.XMLHTTP.3.0');
                    }
                    return request;
                } 
            //]]>
        </script>
        
      3. 在母版页的body标签中添加如下代码。

        <body onbeforeunload="bodyUnload();" onmousedown="somefunction()">
        

      【讨论】:

        【解决方案7】:

        使用这个:

         window.onbeforeunload = function () {
            if (!validNavigation) {
                endSession();
            }
        }
        

        jsfiddle

        在浏览器或标签页关闭时阻止 F5、表单提交、输入点击和关闭/终止会话,在 ie8+ 和现代浏览器中测试,享受!

        【讨论】:

        • 请考虑此解决方案仅在您的用户允许执行 javascript 的情况下才有效,因此这可能是一个严重的安全问题。
        • 对于那些想要使用这个解决方案的人来说,这个代码不处理浏览器刷新按钮按下、后退按钮按下、前进按钮按下,以及在浏览器的 URL 栏中按 Enter。当任何上述事件发生时以及标签/浏览器关闭时都会触发注销
        【解决方案8】:

        目前不是完美但最好的解决方案:

        var spcKey = false;
        var hover = true;
        var contextMenu = false;
        
        function spc(e) {
            return ((e.altKey || e.ctrlKey || e.keyCode == 91 || e.keyCode==87) && e.keyCode!=82 && e.keyCode!=116);
        }
        
        $(document).hover(function () {
            hover = true;
            contextMenu = false;
            spcKey = false;
        }, function () {
            hover = false;
        }).keydown(function (e) {
            if (spc(e) == false) {
                hover = true;
                spcKey = false;
            }
            else {
                spcKey = true;
            }
        }).keyup(function (e) {
            if (spc(e)) {
                spcKey = false;
            }
        }).contextmenu(function (e) {
            contextMenu = true;
        }).click(function () {
            hover = true;
            contextMenu = false;
        });
        
        window.addEventListener('focus', function () {
            spcKey = false;
        });
        window.addEventListener('blur', function () {
            hover = false;
        });
        
        window.onbeforeunload = function (e) {
            if ((hover == false || spcKey == true) && contextMenu==false) {
                window.setTimeout(goToLoginPage, 100);
                $.ajax({
                    url: "/Account/Logoff",
                    type: 'post',
                    data: $("#logoutForm").serialize(),
                });
                return "Oturumunuz kapatıldı.";
            }
            return;
        };
        
        function goToLoginPage() {
            hover = true;
            spcKey = false;
            contextMenu = false;
            location.href = "/Account/Login";
        }
        

        【讨论】:

          【解决方案9】:

          要关闭浏览器,您可以将以下代码放入您的 web.config 中:

          <system.web>
              <sessionState mode="InProc"></sessionState>
           </system.web>
          

          当浏览器关闭时它会破坏你的会话,但它不适用于标签关闭。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2015-04-23
            • 2018-12-09
            • 1970-01-01
            • 2014-09-04
            • 2013-11-03
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多