java - session 结束后,如何在Java Web Application中自动注销用户的登录页面?

标签 java servlets jakarta-ee servlet-filters stripes

要求是,如果用户会话无效,则应自动将用户重定向到登录页面,而不进行任何服务器调用。定期调用服务器的解决方案不适合,因为它会增加服务器负载。

最佳答案

我明白你的意思,你不想打任何电话来管理会议,实际上这是一个很好的问题。

如果没有完善的客户端逻辑,则可能是简单的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.如果最大允许会话为一个,则如果会话是从另一个系统进行的,则AJAX请求将失败。需要处理它以重定向到登录页面。
2.使用ajaxStart()而不是ajaxComplete()使服务器和浏览器之间的idleTime值完全同步。

要求
1. jQuery

比较当前实施方案


1.在http响应中设置Refresh标头。 (不适用于AJAX请求)

response.setHeader("Refresh", "60; URL=login.jsp");



在HTML中设置元刷新标记(不适用于AJAX请求)


<meta http-equiv="refresh" content="60; url=login.jsp">



配置活动检查器
通过重复的AJAX请求使会话保持活动状态。跟踪空闲时间,并在超时后发出注销请求。
毫无疑问,这是一个简单逻辑的好人。但我只想提出自己的看法。


如果每分钟发出2个请求以保持会话活动和5万活跃用户,则会对性能产生影响。每分钟10万个请求。
选项卡间的通信如果两个选项卡都打开,则一个选项卡正在接收活动,而另一个选项卡未接收活动,即使其他选项卡中存在活动,该选项卡也会触发注销请求并使会话无效。 (但可以处理)
强制注销方法它是客户端在服务器上主导的会话无效。

关于java - session 结束后,如何在Java Web Application中自动注销用户的登录页面?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42853569/

相关文章:

java - 尝试打印包含来自 JavaFx 的图像的节点时出现像素化结果

mysql - 使用 servlet 和 jsp 从单个应用程序连接到多个数据库

java - MessageDrivenBean 中的 Finalize 方法

java - com.day.cq.search.impl.SimpleSearchImpl 是否公开了 addPredicate() 方法?

Eclipse 中的 Java EE 模块依赖项页面缺少项目

java - 为什么java排名第一?

java - 集合 addAll removeAll 返回 boolean 值

java - 如何在 Java 应用程序中禁用不安全的 HTTP 方法

java - 如何检查请求的 URL 是否是 servlet(在过滤器中)?

java - 使用tomcat时无法使用java包