java 会话到期后自动注销
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3201991/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Auto Log Off once the session expires
提问by sarah
Our application logs off after 30 min and gets redirected to login page,i am specifying session timeout in web.xml and using a requestProcessor for redirecting.I want to show to the user a message saying your session got expired once the session expires,how can i do that.Auto log off ? I would like to prompt the error message on the page"The session is timeout, please login again" . Then how could I detect the session is timeout? will any methods trigger automatically?
我们的应用程序在 30 分钟后注销并重定向到登录页面,我在 web.xml 中指定会话超时并使用 requestProcessor 进行重定向。我想向用户显示一条消息,说会话过期后您的会话已过期,如何我可以这样做。自动注销?我想在页面上提示错误信息“会话超时,请重新登录”。那我怎么能检测到会话超时呢?任何方法都会自动触发吗?
回答by BalusC
Create an activity checker which checks every minute if any user activity has taken place (mouseclick, keypress) and performs a heartbeat to the server side to keep the session alive when the user is active and does nothing when the user is not active. When there is no activity for 30 minutes (or whatever default session timeout is been set on server side), then perform a redirect.
创建一个活动检查器,它每分钟检查是否发生了任何用户活动(鼠标点击、按键),并向服务器端执行心跳以在用户活动时保持会话活动,而在用户不活动时不执行任何操作。如果 30 分钟内没有活动(或服务器端设置的任何默认会话超时),则执行重定向。
Here's a kickoff example with little help of jQueryto bind click and keypress events and fire ajax request.
这是一个启动示例,几乎没有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>
Create a Servletwhich listens on /heartbeatand does basically just the following:
创建一个Servlet监听/heartbeat并基本上只执行以下操作:
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) {
request.getSession();
}
to keep the session alive.
保持会话活跃。
When you store the logged-in user in the session, it will be "automagically" logged out whenever the session expires. So you don't need to manually logout the user.
当您将登录用户存储在会话中时,只要会话过期,它就会“自动”注销。所以你不需要手动注销用户。
回答by JoseK
Create a Listener class implementing HttpSessionListenerand define it in web.xml
创建一个 Listener 类实现HttpSessionListener并在 web.xml 中定义它
This will notify you when any session is destroyed. Use the sessionDestroyed()method.
这将在任何会话被破坏时通知您。使用sessionDestroyed()方法。
See a full example here:
在此处查看完整示例:
http://www.mkyong.com/servlet/a-simple-httpsessionlistener-example-active-sessions-counter/
http://www.mkyong.com/servlet/a-simple-httpsessionlistener-example-active-sessions-counter/
回答by Script Runner
Include a javascript utility function inside your JSP and ping the server every 31 minutes. The above mentioned utility function should be using setTimeout() JS function internally.
在您的 JSP 中包含一个 javascript 实用程序函数并每 31 分钟 ping 服务器一次。上面提到的实用函数应该在内部使用 setTimeout() JS 函数。
setTimeout ( "checkServerSession()", /* intervalInMilliSeconds */ 31000);
Note that
注意
checkServerSession()
检查服务器会话()
is a regular JS function which may fire HTTP requests. If the request is successful session exists otherwise show the prompt to the user.
是一个常规的 JS 函数,它可能会触发 HTTP 请求。如果请求成功会话存在,否则向用户显示提示。
回答by futureelite7
If you're using servlet sessions, you can check to see if the session the jsp / servlet is returning is new using the isNew() method. If yes, then the user's session has expired and you can display the relevant messages.
如果您正在使用 servlet 会话,您可以使用 isNew() 方法检查 jsp/servlet 返回的会话是否是新的。如果是,则用户的会话已过期,您可以显示相关消息。
回答by PraveenKumar Lalasangi
Either it may be simple servlet, spring-mvc or spring-security auto logout is not possible without perfect client side logic.
Considering application will have both type of request
如果没有完美的客户端逻辑,它可能是简单的 servlet、spring-mvc 或 spring-security 自动注销是不可能的。
考虑到应用程序将有两种类型的请求
- AJAX and
- form submission/page reload
- AJAX 和
- 表单提交/页面重新加载
Auto logout needs very calculated logic. Presenting my autologout functionality implementation with following
自动注销需要非常计算的逻辑。使用以下内容展示我的自动注销功能实现
Advantages.
好处。
1. 没有使用额外的调用/请求来实现这一点。如果超过 10k 的活跃用户和额外的调用来实现自动注销,则考虑性能影响。
2. 使用标签的一条线路配置。
3. 即使用户打开多个标签或多个窗口也能完美运行。
4. 会话失效前30秒提示您,如果您填写了表单没有提交,您可以保持会话活跃(一键延长会话)。因此用户不太可能丢失未保存的数据。
Usage
用法
1. Include auto logout script in required JSP pages as given below.
1. 在所需的 JSP 页面中包含自动注销脚本,如下所示。
....
</body>
<jsp:include page="../template/autologout-script.jsp"></jsp:include>
</html>
2. Create a JSP page, autologout-script.jsp and add below code.Note: No editing/configuring is required
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. Configure session attributes to configuring timeout settingNote: Configure this after session creation. You can implement HttpSessionListener sessionCreated method and set the following configuration as per your requirement.
3. 配置会话属性以配置超时设置注意:在会话创建后进行配置。您可以实现 HttpSessionListener sessionCreated 方法并根据您的要求设置以下配置。
session.setMaxInactiveInterval(300);
session.setAttribute("timeOutTimeInSeconds", 300);
session.setAttribute("showTimerTimeInSeconds", 30);
4. Add below html for displaying timer.
Note: it can be moved to autologout-script template page if you are good at CSS. Hence you can avoid to add this in each and every page.
Include bootstrap or add your custom css.
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>
That is all about a simple auto logout implementation.
You can download working example from my github repository
Autologout using simple servlet example
Autologout using spring-security java configuration example
Autologout using spring-security xml configuration example
这就是一个简单的自动注销实现。您可以从我的 github 存储库下载工作示例
Autologout using simple servlet example
Autologout using spring-security java 配置示例
Autologout using spring-security xml 配置示例
Logic Explained
逻辑解释
Case 1: On Page load案例 1:页面加载
这里的逻辑很简单,在页面加载时将间隔定时器设置为 maxInactiveInterval。超时后重定向到登录页面。
Case 2: Keep track AJAX calls案例 2:跟踪 AJAX 调用
现在考虑 AJAX 请求,您可以使用 jquery 的 .ajaxStart() 或 .ajaxComplete() 回调,以便在触发任何 ajax 请求时您可以重置间隔。
Case 3: Tracking multi tab/window activity案例 3:跟踪多标签/窗口活动
进行标签间通信以同步每个标签的状态。在更改事件上使用 localStorage。
Limitations/Improvements required
1. If maximum allowed session is one, if session is taken from another system, AJAX request will fail. It needs to be handled to redirect to login page.
2. Use ajaxStart() instead of ajaxComplete() to have exact sync of idleTime values between server and browser.
需要的限制/改进
1. 如果允许的最大会话是一个,如果会话是从另一个系统获取的,AJAX 请求将失败。需要处理重定向到登录页面。
2. 使用 ajaxStart() 而不是 ajaxComplete() 在服务器和浏览器之间精确同步 idleTime 值。
Requirements
1. Jquery
需求
1. jQuery
Alternatives to current implementation compared
比较当前实现的替代方案
1. Setting Refresh header在 http 响应中设置刷新标头。(Not works for AJAX requests)(不适用于 AJAX 请求)
response.setHeader("Refresh", "60; URL=login.jsp");
- Setting meta refresh tagin HTML (Not works for AJAX requests)
- 在 HTML 中设置元刷新标记(不适用于 AJAX 请求)
<meta http-equiv="refresh" content="60; url=login.jsp">
- Configuring Activity checkerKeeps session alive by repeated AJAX request. Tracks idle time and makes logout request after timeout.
No doubt it is a good one with simple logic. But i want to just ink my observations.- Performance impactif 2 requests are made per minute to keep session alive and 50k active users. 100k requests per minute.
- Intertab communicationIf two tabs are open, one tab is receiving activity but other tab is not receiving activity, that tab fires logout request and invalidate session even though activity is present in other tab. (But can be handled)
- Force logout approachIt is a client is dominated over server to invalidate session.
- 配置活动检查器通过重复的 AJAX 请求使会话保持活动状态。跟踪空闲时间并在超时后提出注销请求。
毫无疑问,这是一本逻辑简单的好书。但我只想写下我的观察。- 如果每分钟发出 2 个请求以保持会话活动和 50k 活跃用户,则性能影响。每分钟 10 万个请求。
- Intertab 通信如果两个选项卡打开,一个选项卡正在接收活动,而另一个选项卡没有接收活动,即使其他选项卡中存在活动,该选项卡也会触发注销请求并使会话无效。(但可以处理)
- 强制注销方法客户端控制服务器使会话无效。


