会话到期后自动注销

时间:2010-07-08 08:58:46

标签: java servlets java-ee

我们的应用程序在30分钟后注销并被重定向到登录页面,我在web.xml中指定会话超时并使用requestProcessor进行重定向。我想向用户显示一条消息,说明会话在会话后过期到期,我该怎么做。自动注销? 我想提示页面上的错误消息“会话超时,请再次登录”。然后我怎么能检测到会话超时?任何方法会自动触发吗?

5 个答案:

答案 0 :(得分:10)

创建一个活动检查器,检查每一分钟是否发生任何用户活动(mouseclick,keypress)并对服务器端执行心跳以在用户处于活动状态时保持会话处于活动状态,并在用户未处于活动状态时不执行任何操作。如果30分钟内没有活动(或者在服务器端设置了默认会话超时),则执行重定向。

这是一个启动示例,很少有jQuery的帮助来绑定click和keypress事件并触发ajax请求。

<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script>
    $(document).ready(function() {
        $.active = false;
        $('body').bind('click keypress', function() { $.active = true; });
        checkActivity(1800000, 60000, 0); // timeout = 30 minutes, interval = 1 minute.
    });

    function checkActivity(timeout, interval, elapsed) {
        if ($.active) {
            elapsed = 0;
            $.active = false;
            $.get('heartbeat');
        }
        if (elapsed < timeout) {
            elapsed += interval;
            setTimeout(function() {
                checkActivity(timeout, interval, elapsed);
            }, interval);
        } else {
            window.location = 'http://example.com/expired'; // Redirect to "session expired" page.
        }
    }
</script>

创建一个Servlet来监听/heartbeat,基本上只做以下几点:

@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
    request.getSession();
}

让会话保持活力。

当您将登录用户存储在会话中时,只要会话过期,它就会“自动”注销。因此,您无需手动注销用户。

答案 1 :(得分:2)

创建一个实现HttpSessionListener的Listener类,并在web.xml中定义它

这会在任何会话被销毁时通知您。使用sessionDestroyed()方法。

请参阅此处的完整示例:

http://www.mkyong.com/servlet/a-simple-httpsessionlistener-example-active-sessions-counter/

答案 2 :(得分:0)

如果您正在使用servlet会话,则可以使用isNew()方法检查jsp / servlet返回的会话是否是新的。如果是,则用户的会话已过期,您可以显示相关消息。

答案 3 :(得分:0)

在JSP中包含一个javascript实用程序函数,每隔31分钟ping一次服务器。 上面提到的实用函数应该在内部使用setTimeout()JS函数。

setTimeout ( "checkServerSession()",  /* intervalInMilliSeconds */ 31000);

请注意

  

checkServerSession()

是一个常规的JS函数,可以触发HTTP请求。如果请求成功,则会话存在,否则向用户显示提示。

答案 4 :(得分:0)

可能是简单的servlet,如果没有完善的客户端逻辑,spring-mvc或spring-security自动注销是不可能的。
考虑到应用程序将同时具有两种类型的请求

  • AJAX和
  • 提交表单/重新加载页面

自动注销需要经过精心计算的逻辑。通过以下

展示我的自动注销功能实现

优势。


1.无需额外的呼叫/请求即可实现此目的。如果活动用户超过1万,并且要实现自动注销的额外呼叫,则要考虑对性能的影响。
2.使用标签进行一线配置。
3.即使用户打开多个选项卡或多个窗口也可以正常工作。
4.它会在会话无效30秒之前提示您,因此,如果您填写了表单但未提交,则可以使会话保持活动状态(一键扩展会话)。因此,用户不太可能丢失未保存的数据。

用法


1。如下所示,在所需的JSP页面中包括自动注销脚本。

    ....
    </body>
    <jsp:include page="../template/autologout-script.jsp"></jsp:include>
</html>

2。创建一个JSP页面autologout-script.jsp并添加以下代码。 注意:无需编辑/配置

<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>

<script>
$(document).ready(function()
{
    var timeOutTimeInSeconds = ${ timeOutTimeInSeconds }; 
    var showTimerTimeInSeconds= ${ showTimerTimeInSeconds };

    var sessionCheckIntervalId = setInterval(redirectToLoginPage, timeOutTimeInSeconds * 1000);
    var timerDisplayIntervalId = setInterval(showTimer, (timeOutTimeInSeconds - showTimerTimeInSeconds) * 1000);
    var badgeTimerId;
    window.localStorage.setItem("AjaxRequestFired", new Date());

    function redirectToLoginPage(){
        //location.href =  '<c:url value="/" />'+'${loginPageUrl}';
        window.location.reload();
    }

    $(document).ajaxComplete(function () {
        resetTimer();
    });

    $(window).bind('storage', function (e) {
         if(e.originalEvent.key == "AjaxRequestFired"){
             console.log("Request sent from another tab, hence resetting timer")
             resetTimer();
         }
    });

    function resetTimer()
    {
        showTimerTimeInSeconds= ${ showTimerTimeInSeconds };

        console.log("timeOutTimeInSeconds : "+timeOutTimeInSeconds)
        window.localStorage.setItem("AjaxRequestFired", new Date());

        window.clearInterval(sessionCheckIntervalId);
        sessionCheckIntervalId = setInterval(redirectToLoginPage, timeOutTimeInSeconds * 1000);

        window.clearInterval(timerDisplayIntervalId);
        timerDisplayIntervalId = setInterval(showTimer, (timeOutTimeInSeconds - showTimerTimeInSeconds) * 1000);

        hideTimer();
    }

    function showTimer()
    {
        $('#sessionTimeRemaining').show();
        $('#sessionTimeRemainingBadge').html(showTimerTimeInSeconds--);
        window.clearInterval(timerDisplayIntervalId);
        badgeTimerId = setInterval(function(){
            $('#sessionTimeRemainingBadge').html(showTimerTimeInSeconds--);
        }, 1000);
    }

    function hideTimer()
    {
        window.clearInterval(badgeTimerId);
        $('#sessionTimeRemaining').hide();
    }
});
</script>

3。配置会话属性以配置超时设置 注意:在会话创建后配置此。您可以实现HttpSessionListener sessionCreated方法,并根据需要设置以下配置。

session.setMaxInactiveInterval(300);

session.setAttribute("timeOutTimeInSeconds", 300);
session.setAttribute("showTimerTimeInSeconds", 30);

4。在html下方添加用于显示计时器。
注意:如果您擅长CSS,可以将其移至autologout-script模板页面。因此,您可以避免在每个页面中添加它。
包括引导程序或添加自定义CSS。

<span class="badge badge-primary" title="click to keep session alive" id="sessionTimeRemaining" 
    onclick="ajaxSessionRefresh()" style="display:none;">
    <i class="badge badge-danger" id="sessionTimeRemainingBadge" style="float:left">30</i>
     &nbsp; 
     <small>Refresh</small>
     <i class="glyphicon glyphicon-refresh"></i>
</span>

enter image description here

这就是简单的自动注销实现。 您可以从我的github存储库下载工作示例
Autologout using simple servlet example
Autologout using spring-security java configuration example
Autologout using spring-security xml configuration example

逻辑解释


案例1:页面加载
这里的逻辑很简单,页面加载设置计时器的间隔等于maxInactiveInterval。超时后重定向到登录页面。
案例2:跟踪AJAX调用
现在考虑AJAX请求,您可以使用jquery的.ajaxStart()或.ajaxComplete()回调,这样,如果触发了任何ajax请求,您可以重置时间间隔。
案例3:跟踪多个标签页/窗口活动
进行表间通信以同步每个选项卡的状态。在发生更改事件时使用了localStorage。

所需的限制/改进
1.如果最大允许会话数为1,则如果会话是从另一个系统进行的,则AJAX请求将失败。需要处理它以重定向到登录页面。
2.使用ajaxStart()而不是ajaxComplete()在服务器和浏览器之间实现idleTime值的精确同步。

要求
1. jQuery

当前实施方案的替代方案


1.在http响应中设置刷新标题(不适用于AJAX请求)

response.setHeader("Refresh", "60; URL=login.jsp");
  1. 在HTML 中设置元刷新标记(不适用于AJAX请求)
<meta http-equiv="refresh" content="60; url=login.jsp">
  1. 配置活动检查器 通过重复的AJAX请求使会话保持活动状态。跟踪空闲时间并在超时后发出注销请求。
    毫无疑问,这是一个简单逻辑的好人。但我只想提出自己的看法。
    • 对性能的影响,如果每分钟发出2个请求以保持会话活动和5万活跃用户。每分钟10万个请求。
    • 选项卡间通信如果两个选项卡都打开,则一个选项卡正在接收活动,而另一个选项卡未接收活动,即使其他选项卡中存在活动,该选项卡也会触发注销请求并使会话无效。 (但可以处理)
    • 强制注销方法。这是客户端主导着服务器,使会话无效。