题
我们的应用程序在30分钟后注销并被重定向到登录页面,我正在web中指定会话超时。xml并使用requestProcessor进行重定向。我想向用户显示一条消息,说明一旦会话过期,您的会话已过期,我该如何做到这一点。自动注销?我想在页面上提示错误消息"会话超时,请再次登录"。那么我怎么能检测到会话超时?任何方法都会自动触发吗?
解决方案
创建一个活动检查器,每分钟检查是否发生了任何用户活动(mouseclick,keypress),并向服务器端执行心跳,以在用户处于活动状态时保持会话活动,而在用户不处于活动如果30分钟内没有活动(或者服务器端设置了任何默认会话超时),则执行重定向。
这里有一个很少帮助的开球例子 jQuery的 绑定点击和按键事件并触发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();
}
让会议保持活力。
当您将登录用户存储在会话中时,每当会话过期时,它都会"自动"注销。所以你不需要手动注销用户。
其他提示
创建一个实现生成的侦听器类,并在web.xml中定义它
这将在任何会话被销毁时通知您。使用HttpSessionListener
方法。
在此处查看一个完整的示例:
http://www.mkyong。com / servlet / a-simple-httpsessionListener-examptive-sessions-counter /
它可能是简单的servlet,没有完美的客户端逻辑,不可能进行Spring-MVC或Spring-Security自动注销。
考虑应用程序将具有两种类型的请求
- ajax和
- 表格提交/页重载
自动注销需要非常计算的逻辑。介绍我的自动突发功能实现,下面
优点。
1.不使用额外的呼叫/请求来实现这一目标。考虑到超过10k有效的用户和额外的呼叫来实现自动注销,会影响性能影响。
2.使用标签的一行配置。
3.即使用户打开多个标签或多个窗口,也可以完美地工作。
4.它在30秒的会话无效之前将您充满了解您,因此如果您填充了表单而未提交,则可以保持会话活动(通过单击扩展会话)。因此用户不太可能松开未撤下的数据。
用法
1。包括如下所示的所需JSP页面中的自动注销脚本。
....
</body>
<jsp:include page="../template/autologout-script.jsp"></jsp:include>
</html>
.
2。创建JSP页面,AutogOut-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会话创建的方法并设置以下配置。
session.setMaxInactiveInterval(300);
session.setAttribute("timeOutTimeInSeconds", 300);
session.setAttribute("showTimerTimeInSeconds", 30);
.
4。添加以下HTML以显示计时器。
注意:如果您擅长CSS,它可以移动到“自动脚本模板”页面。因此,您可以避免在每个页面中添加此页面。
包括引导或添加自定义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存储库下载工作示例
使用简单servlet示例
使用spring-security java配置excutize
自动解决spring-security xml配置examply excext
逻辑解释
案例1:页面加载
这里逻辑很简单,页面加载间隔Equlas的计时器到MaxInactiveInterval。超时重定向到登录页面。
案例2:保持跟踪Ajax调用
现在考虑ajax请求,您可以使用.ajaxstart()或.ajaxcomplete()jQuery的回调,以便如果解雇任何AJAX请求,则可以重置间隔。
案例3:跟踪多标签/窗口活动
Intertab通信是为了同步每个选项卡的状态。在更改事件时使用localstorage。
限制/改进所需
1.如果最大允许的会话是一个,如果从另一个系统中拍摄会话,则Ajax请求将失败。需要处理以重定向到登录页面。
2.使用ajaxstart()而不是ajaxcomplete()在服务器和浏览器之间精确同步iDletime值。
要求
1. jquery
电流实现的替代方案比较
1. <强>在HTTP响应中设置刷新标题。 (不适用于Ajax请求)
response.setHeader("Refresh", "60; URL=login.jsp");
.
- 在html 中设置元刷新标记(不适用于ajax请求)
- 配置活动检查
通过重复的AJAX请求保持活动。追踪空闲时间并在超时后进行注销请求。
毫无疑问,这是一个很好的逻辑。但我想只是墨水我的观察。- 性能影响如果每分钟进行2个请求以保持会话活动和50k活跃的用户。每分钟100K请求。
- Intertab通信如果打开两个选项卡,则一个选项卡正在接收活动,但其他选项卡未接收活动,即表示其他选项卡中的活动触发注销请求和无效会话。 (但可以处理)
- 力注销方法它是一个客户端在服务器上占主导地位,使其无效。
<meta http-equiv="refresh" content="60; url=login.jsp">
.
如果您正在使用servlet会话,则可以检查jsp / servlet是否返回的会话是新的,使用iSnew()方法是新的。如果是,则用户的会话已过期,您可以显示相关消息。
在JSP中包含JavaScript实用程序函数,每31分钟为服务器Ping服务器。 上面提到的实用程序函数应使用SetTimeOut()JS在内部函数。
setTimeout ( "checkServerSession()", /* intervalInMilliSeconds */ 31000);
.
注意
checkserversession()
是一个常规的js函数,可以闪光HTTP请求。如果请求是成功的会话,则存在于向用户显示提示。