要求是,如果用户会话无效,则应自动将用户重定向到登录页面,而不进行任何服务器调用。定期调用服务器的解决方案不适合,因为它会增加服务器负载。
最佳答案
我明白你的意思,你不想打任何电话来管理会议,实际上这是一个很好的问题。
如果没有完善的客户端逻辑,则可能是简单的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>
<small>Refresh</small>
<i class="glyphicon glyphicon-refresh"></i>
</span>
这就是简单的自动注销实现。
您可以从我的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/