4

在用户单击注销按钮时的网页上,我有一个 JavaScript 函数,它清除存储在 MongoDB 上的用户会话。它工作正常。

我还想在用户关闭浏览器时清除用户会话。这是我面临的问题:当用户单击刷新图标时,将调用注销功能。我只希望在关闭浏览器时调用此函数。

我可以阻止这个函数在页面刷新时调用吗?

我的逻辑是在浏览器关闭时清理会话。我正在删除 MongoDB 上的会话。有没有更好的方法来管理会话?

var isRefresh = false;
$(window).keydown(function (event) {
    if (event.keyCode == 116) { // User presses F5 to refresh
        refresh = true;
    }
});

// Calls the logout function when you close the browser thus cleans the session data.
var windowsCloseEventListener = window.attachEvent || window.addEventListener;
var chkForBrowserCloseEvents = window.attachEvent ? 'onbeforeunload' : 'beforeunload'; /// make IE7, IE8 compitable
windowsCloseEventListener(chkForBrowserCloseEvents, function (e) { // For >=IE7, Chrome, Firefox
    if (!isRefresh) {
        $scope.logout();
    }
});
4

6 回答 6

2

为了更好地管理会话并解决用户按下浏览器刷新的问题,您需要

  • 关闭窗口时删除注销功能。
  • 在客户端和服务器上实施 InActivity 监视器,如果用户在一段时间内不活动,它将清除会话。因此,如果用户关闭浏览器,MongoDB 中的会话将持续一段时间,直到服务器清除它。
  • 实现从客户端到服务器的 keepalive ping,如果用户在页面上处于活动状态,它将每隔设置的时间间隔 ping 服务器。为了减少网络流量,您可以在使用 AJAX 或 RESTful api 调用服务器时重新安排 keepalive。
  • 将浏览器中的用户会话保存在本地存储中,以便在浏览器刷新时可以重新读取会话。

这个 InActivity 监视器可以是一个很好的起点。https://github.com/HackedByChinese/ng-idle/blob/develop/src/angular-idle.js。我已经在我的 Angular 项目中完成了上述所有工作。希望有帮助。

于 2014-11-06T15:13:31.403 回答
2

据我所知,您实际上无法测试浏览器是否被关闭;您只能测试正在关闭的窗口(或选项卡)。这通常就足够了,除非当然发生页面刷新,因为它既可以关闭又可以重新打开窗口或选项卡内的网页。需要的是一个事件处理程序,用于单击浏览器的页面刷新按钮,但我不确定是否存在。这里有一些东西:

如何显示“您确定要离开此页面吗?” 何时提交更改?

并且

处理浏览器关闭事件和页面刷新

我在尝试查找有关页面刷新事件处理程序的内容时遇到的一件事是使用“本地存储”的概念。作为 on-before-unload 处理程序的一部分,您可以将一个带有时间戳的小数据项放入本地存储中。在服务器上激活一种计时器,并等待该时间到期,然后再删除会话。加载页面后,测试该数据项的本地存储。如果它存在并且时间戳是最近的,则您知道页面已刷新,并且可以根据知道的情况做适当的事情——比如向服务器发送 AJAX 消息,告诉它暂时不要删除会话。

于 2014-10-27T18:30:53.423 回答
2

正如 Alex 建议的那样,您可以使用会话 Cookie来检查您的网站是否在当前会话中被看到(IE7+ 支持)。

例子

function readCookie(name) {
    var nameEQ = name + "=";
    var ca = document.cookie.split(';');
    for(var i=0;i < ca.length;i++) {
        var c = ca[i];
        while (c.charAt(0)==' ') c = c.substring(1,c.length);
        if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
    }
    return null;
}

var isRefresh = true;
var sessionAlive = readCookie("sessionAlive");
if (sessionAlive === null) {
    isRefresh = false;
    sessionStorage.setItem("sessionAlive", true);
}

var windowsCloseEventListener = window.attachEvent || window.addEventListener;
var chkForBrowserCloseEvents = window.attachEvent ? 'onbeforeunload' : 'beforeunload';
windowsCloseEventListener(chkForBrowserCloseEvents, function (e) {
    if (!isRefresh) {
        $scope.logout();
    }
});

您可以使用sessionStorage,这是更多的 HTML5 方式,查看浏览器是否已关闭(新会话)(IE8+ 支持)。

例子:

var isRefresh = true;
var sessionAlive = sessionStorage.getItem("sessionAlive");
if (sessionAlive === null) {
    isRefresh = false;
    sessionStorage.setItem("sessionAlive", true);
}

var windowsCloseEventListener = window.attachEvent || window.addEventListener;
var chkForBrowserCloseEvents = window.attachEvent ? 'onbeforeunload' : 'beforeunload';
windowsCloseEventListener(chkForBrowserCloseEvents, function (e) {
    if (!isRefresh) {
        $scope.logout();
    }
});

readCookie 取自:http ://www.quirksmode.org/js/cookies.html

于 2014-11-06T18:50:58.170 回答
1

使用带有会话过期的 cookie 应该可以工作。

于 2014-11-05T15:10:58.453 回答
0

WindowEventHandlers.onbeforeunload

window.onbeforeunload = function(e) {
  return 'Dialog text here.';
};

此示例显示 addEventListener 和 attachEvent 方法不能用于 onbeforeunload 事件(Google Chrome 和 Safari 除外):

 if (window.addEventListener) {  // all browsers except IE before version 9
            window.addEventListener ("beforeunload", OnBeforeUnLoad, false);
        }
        else {
            if (window.attachEvent) {   // IE before version 9
                window.attachEvent ("onbeforeunload", OnBeforeUnLoad);
            }
        }

            // the OnBeforeUnLoad method will only be called in Google Chrome and Safari
        function OnBeforeUnLoad () {
            return "All data that you have entered will be lost!";
        }
于 2014-11-04T19:58:10.277 回答
0

您可以使用“onbeforeunload”事件来处理这种情况。

$wnd.onbeforeunload = function(e) {

        var logoutClicked = callSomeFunctionToGetIfLogoutButtonIsClicked();
        if (!logoutClicked) {
            return "Some message";
        }
        return;
    }
于 2014-11-06T18:50:33.127 回答