Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 如何在关闭窗口时注销我的应用程序?_Javascript_Ajax_Jsp_Servlets - Fatal编程技术网

Javascript 如何在关闭窗口时注销我的应用程序?

Javascript 如何在关闭窗口时注销我的应用程序?,javascript,ajax,jsp,servlets,Javascript,Ajax,Jsp,Servlets,在我的聊天应用程序中,我有注销按钮,它工作正常 现在我还需要在关闭浏览器窗口时注销应用程序..如何实现这一点 先谢谢你 将您的注销代码添加到on事件中 在JQuery中,您可以使用该函数。请记住,您没有太多时间,因此可以发送Ajax请求,但结果可能无法到达客户端 另一个技巧是打开一个新的小窗口,并在那里处理注销 window.open("logout url","log out","height=10,width=10,location=no,menubar=no,status=no,title

在我的聊天应用程序中,我有注销按钮,它工作正常

现在我还需要在关闭浏览器窗口时注销应用程序..如何实现这一点


先谢谢你

将您的注销代码添加到on事件中

在JQuery中,您可以使用该函数。请记住,您没有太多时间,因此可以发送Ajax请求,但结果可能无法到达客户端

另一个技巧是打开一个新的小窗口,并在那里处理注销

window.open("logout url","log out","height=10,width=10,location=no,menubar=no,status=no,titlebar=no,toolbar=no",true);
如果要禁用关闭窗口(或至少警告用户),可以使用以下代码:

window.onbeforeunload = function(event) {
    //if you return anything but null, it will warn the user.
    //optionally you can return a string which most browsers show to the user as the warning message.
    return true;
}

另一个技巧是每隔几秒钟对客户端进行ping操作。如果没有回复,则假定用户已关闭窗口、浏览器已崩溃或存在网络问题,结束了聊天会话。在客户端,如果您没有收到此ping包,您可以假设网络连接或服务器有问题,您可以显示注销警告(并可以选择让用户再次登录)。

一些网站正在使用以下脚本检测窗口是否关闭

if(window.screenTop > 10000)
alert("Window is closed");
else
alert("Window stillOpen");
您需要添加正确的操作,而不是
alert()


还要看一看-我认为这是一件需要检测窗口关闭的事情

客户端没有确切的方法可以做到这一点。退出页面时没有触发任何事件。这应该通过服务器上的会话结束事件来完成

您可以尝试使用onbeforeunload或unload,但竞争条件将阻止这种情况发生。而且它们不会因浏览器崩溃、互联网连接中断等而启动。

我通过

window.onunload = function () {
    //logout code here...
}

感谢所有支持我的人……

另一种方法是某种“keepalive”:浏览器页面每隔一分钟左右用一个小ajax请求“ping”服务器。如果服务器未获得常规ping,则会话将关闭,无法再使用

作为优化,如果在此期间向服务器发出了另一个请求,则可以跳过ping

优点:

  • 仍然可以在多个窗口打开时使用
  • F5/刷新没有问题
  • can向服务器提供一些使用情况统计信息
缺点:

  • 当窗口关闭时,在用户注销之前会有一个延迟
  • 使用一点网络带宽
  • 服务器上的额外负载
  • 用户可能担心该页面经常“打电话回家”
  • 更难实施
我从来没有在网络应用程序中这样做过,也不确定我是否会这样做;只是把它作为另一种选择。对于聊天应用来说,这似乎是一个不错的选择,因为服务器需要知道你是否还在那里


与轮询/ping不同,另一种可能是在页面打开时保持“长时间运行的请求”打开。聊天应用程序需要一些这样的套接字来接收新消息和通知。如果页面已关闭,套接字也将关闭,服务器会注意到它已关闭。然后它会等待客户端建立一个新的套接字,如果没有,我们就假定页面已关闭并删除会话。这需要在服务器上安装一些稍微不寻常的软件。

我最近在angularJS应用程序中处理了这个问题-主要问题是,如果你刷新,我不想让你注销,但如果你关闭标签,我确实想让你注销。。onbeforeunload/onunload的Ajax请求不保证等待响应,因此我的解决方案如下:

我在登录时设置了一个sessionStorage cookie,当我得到登录响应时,它只是一个bool设置为true

sessionStorage.setItem('activeSession','true')

显然,在注销时,我们将此标志设置为false

当控制器初始化或使用window.onload(在我的app.js文件中)时,我会检查这个activeSession bool。。如果为false,我有一个小if语句——如果满足条件,我调用我的注销方法ONLOAD,而不是onunload

   var activeSession = sessionStorage.activeSession;
    if (sessionStorage.loggedOutOnAuth) {
        console.log('Logged out due to expiry already')
    }
    else if (!activeSession) {
        sessionStorage.loggedOutOnAuth = true;
        _logout()
    }
基本上,“loggedoutath”bool让我知道我刚刚让你的页面加载过期,因为sessionStorage中没有activeSession,所以你不会陷入循环


这对我来说是一个很好的解决方案,因为我不想实现heartbeat/websocket

我遇到了这个问题,我提出了一个不同的解决方案:

    checkSessionTime();
    $interval(checkSessionTime, 2000);
    function checkSessionTime() {
        var now = (new Date()).getTime();
        if (!$localStorage.lastPing) {
            $localStorage.lastPing = now;
        }

        if ($localStorage.lastPing < now - 5000) {
            $localStorage.lastPing = undefined;
            AuthService.logout();
        } else {
            $localStorage.lastPing = now;
        }
    }
checkSessionTime();
$interval(checkSessionTime,2000);
函数checkSessionTime(){
var now=(new Date()).getTime();
如果(!$localStorage.lastPing){
$localStorage.lastPing=now;
}
如果($localStorage.lastPing
我喜欢这个解决方案,因为它既不增加ping服务器的开销,也不依赖窗口卸载事件。此代码已放入
$app.run

我使用angular和JWT身份验证,这种方式对我来说注销只是为了摆脱身份验证令牌。但是,如果您需要在服务器端完成会话,您可以构建身份验证服务,以便在完成会话时执行一次ping,而不是保持ping以保持会话的活动状态


这个解决方案解决了我的问题,因为我的意图只是防止不想要的用户在关闭标签离开PC时访问某人的帐户。

经过大量搜索后,我用javascript编写了下面的自定义代码,并用c#编写了会话终止的服务器端代码

如果同一个网站在多个选项卡中打开,那么下面的代码将被扩展,这样会话将一直处于活动状态,直到网站的一个选项卡打开为止

//Define global varible 
var isCloseWindow = false;

 //Jquery page load function to register the events

 $(function () {
        //function for onbeforeuload
        window.onbeforeunload = ConfirmLeave;
        //function for onload
        window.onload = ConfirmEnter;

        //mouseover for div which spans the whole browser client area 
        $("div").on('mouseover', (function () {
        //for postback from the page make isCloseWindow global varible to false
            isCloseWindow = false;
        }));
        //mouseout event
        $("div").on('mouseout', (function () {
     //for event raised from tabclose,browserclose etc. the page make isCloseWindow global varible to false
            isCloseWindow = true;
        }));
    });
     //Key board events to track  the  browser tab or browser closed by ctrl+w or alt+f4 key combination
    $(document).keydown(function (e) {
        if (e.key.toUpperCase() == "CONTROL") {
            debugger;
            isCloseWindow = true;
        }
        else if (e.key.toUpperCase() == "ALT") {
            debugger;
            isCloseWindow = true;
        }
        else {
            debugger;
            isCloseWindow = false;
        }
    });

    function ConfirmEnter(event) {
        if (localStorage.getItem("IsPostBack") == null || localStorage.getItem("IsPostBack") == "N") {
            if (localStorage.getItem("tabCounter") == null || Number(localStorage.getItem("tabCounter")) == 0) {
                //cookie is not present
                localStorage.setItem('tabCounter', 1);

            } else {
                localStorage.setItem('tabCounter', Number(localStorage.getItem('tabCounter')) + 1);
            }
        }
        localStorage.setItem("IsPostBack", "N");
    }
    function ConfirmLeave(event) {
        if (event.target.activeElement.innerText == "LOGOUT") {
            localStorage.setItem('tabCounter', 0);
            localStorage.setItem("IsPostBack", "N");
        } else {
            localStorage.setItem("IsPostBack", "Y");
        }
        if ((Number(localStorage.getItem('tabCounter')) == 1 && isCloseWindow == true)) {
            localStorage.setItem('tabCounter', 0);
            localStorage.setItem("IsPostBack", "N");
            **Call Web Method Kill_Session using jquery ajax call**
        } else if (Number(localStorage.getItem('tabCounter')) > 1 && isCloseWindow == true) {
            localStorage.setItem('tabCounter', Number(localStorage.getItem('tabCounter')) - 1);
        }
    }

 //C# server side WebMethod
 [WebMethod]
  public static void Kill_Session()
    {
        HttpContext.Current.Session.Abandon();
    }

对于这个问题,我尝试了两种解决方案:window.onbeforeunload事件和sessionStorage

  • 由于window.onbeforeunload不仅用于关闭浏览器,而且还用于重定向、选项卡刷新、新建选项卡,因此
    //Define global varible 
    var isCloseWindow = false;
    
     //Jquery page load function to register the events
    
     $(function () {
            //function for onbeforeuload
            window.onbeforeunload = ConfirmLeave;
            //function for onload
            window.onload = ConfirmEnter;
    
            //mouseover for div which spans the whole browser client area 
            $("div").on('mouseover', (function () {
            //for postback from the page make isCloseWindow global varible to false
                isCloseWindow = false;
            }));
            //mouseout event
            $("div").on('mouseout', (function () {
         //for event raised from tabclose,browserclose etc. the page make isCloseWindow global varible to false
                isCloseWindow = true;
            }));
        });
         //Key board events to track  the  browser tab or browser closed by ctrl+w or alt+f4 key combination
        $(document).keydown(function (e) {
            if (e.key.toUpperCase() == "CONTROL") {
                debugger;
                isCloseWindow = true;
            }
            else if (e.key.toUpperCase() == "ALT") {
                debugger;
                isCloseWindow = true;
            }
            else {
                debugger;
                isCloseWindow = false;
            }
        });
    
        function ConfirmEnter(event) {
            if (localStorage.getItem("IsPostBack") == null || localStorage.getItem("IsPostBack") == "N") {
                if (localStorage.getItem("tabCounter") == null || Number(localStorage.getItem("tabCounter")) == 0) {
                    //cookie is not present
                    localStorage.setItem('tabCounter', 1);
    
                } else {
                    localStorage.setItem('tabCounter', Number(localStorage.getItem('tabCounter')) + 1);
                }
            }
            localStorage.setItem("IsPostBack", "N");
        }
        function ConfirmLeave(event) {
            if (event.target.activeElement.innerText == "LOGOUT") {
                localStorage.setItem('tabCounter', 0);
                localStorage.setItem("IsPostBack", "N");
            } else {
                localStorage.setItem("IsPostBack", "Y");
            }
            if ((Number(localStorage.getItem('tabCounter')) == 1 && isCloseWindow == true)) {
                localStorage.setItem('tabCounter', 0);
                localStorage.setItem("IsPostBack", "N");
                **Call Web Method Kill_Session using jquery ajax call**
            } else if (Number(localStorage.getItem('tabCounter')) > 1 && isCloseWindow == true) {
                localStorage.setItem('tabCounter', Number(localStorage.getItem('tabCounter')) - 1);
            }
        }
    
     //C# server side WebMethod
     [WebMethod]
      public static void Kill_Session()
        {
            HttpContext.Current.Session.Abandon();
        }
    
    tabOrBrowserStillAliveInterval;
    
    constructor() {
      // system should logout if the browser or last opened tab was closed (in 15sec after closing)
      if (this.wasBrowserOrTabClosedAfterSignin()) {
        this.logOut();
      }
    
      // every 15sec update browserOrTabActiveTimestamp property with new timestamp
      this.setBrowserOrTabActiveTimestamp(new Date());
      this.tabOrBrowserStillAliveInterval = setInterval(() => {
        this.setBrowserOrTabActiveTimestamp(new Date());
      }, 15000);
    }
    
    signin() {
      // ...
      this.setBrowserOrTabActiveTimestamp(new Date());
    }
    
    setBrowserOrTabActiveTimestamp(timeStamp: Date) {
      localStorage.setItem(
        'browserOrTabActiveSessionTimestamp',
        `${timeStamp.getTime()}`
      );
    }
    
    wasBrowserOrTabClosedAfterSignin(): boolean {
      const value = localStorage.getItem('browserOrTabActiveSessionTimestamp');
    
      const lastTrackedTimeStampWhenAppWasAlive = value
        ? new Date(Number(value))
        : null;
      const currentTimestamp = new Date();
      const differenceInSec = moment(currentTimestamp).diff(
        moment(lastTrackedTimeStampWhenAppWasAlive),
        'seconds'
      );
    
      // if difference between current timestamp and last tracked timestamp when app was alive
      // is more than 15sec (if user close browser or all opened *your app* tabs more than 15sec ago)
      return !!lastTrackedTimeStampWhenAppWasAlive && differenceInSec > 15;
    }