在Web开发中,会话管理是一个非常重要的环节,它涉及到用户的登录状态、权限控制以及数据的安全性。在某些应用场景中,我们希望用户的会话在他们活跃时能够自动延长,以避免因会话超时而被迫重新登录,影响用户体验。本文将通过一个实际的Java Web应用示例,展示如何实现这一功能。
技术栈简介
- Java Servlet API:用于处理HTTP请求和响应。
- JQuery:前端JavaScript库,用于处理用户交互和发送Ajax请求。
- Tomcat:作为嵌入式服务器,用于运行和测试Web应用。
实现步骤
1. 配置Servlet
首先,我们需要创建几个Servlet来处理用户的登录、登出以及会话刷新。
@WebServlet(name = "securedServlet", urlPatterns = {"/"})
public class MySecuredServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
Principal principal = req.getUserPrincipal();
if (principal == null || !req.isUserInRole("employee")) {
LoginHandlerServlet.forwardToLogin(req, resp, null);
return;
}
req.setAttribute("user", req.getRemoteUser());
req.getRequestDispatcher("/employee-page.jsp").forward(req, resp);
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doGet(req, resp);
}
}
2. 实现会话刷新Servlet
这个Servlet用于在用户活跃时刷新会话,防止会话超时。
@WebServlet(name = "refreshServlet", urlPatterns = {"/refreshSession"})
public class RefreshSessionServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) {
System.out.println("refreshing session");
if (!req.isUserInRole("employee")) {
System.err.println("User logged out already, set higher setMaxInactiveInterval() ");
resp.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
}
HttpSession session = req.getSession();
if (session == null) {
System.err.println("cannot renew session");
}
}
}
3. 实现HttpSessionListener
通过实现HttpSessionListener
接口,我们可以在会话创建时设置一个自定义的超时时间。
@WebListener
public class MySessionListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent se) {
System.out.println("-- HttpSessionListener#sessionCreated invoked --");
HttpSession session = se.getSession();
System.out.println("session id: " + session.getId());
session.setMaxInactiveInterval(120); // in seconds
}
@Override
public void sessionDestroyed(HttpSessionEvent se) {
System.out.println("-- HttpSessionListener#sessionDestroyed invoked --");
}
}
4. 前端实现
在前端,我们使用JQuery来监测用户的活跃状态,并定期发送Ajax请求到服务器以刷新会话。
<html>
<body>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
var lastActiveTime = new Date().getTime();
$(document).ready(function() {
$('body').bind('click mousemove keypress scroll resize', function() {
lastActiveTime = new Date().getTime();
});
setInterval(checkIdleTime, 30000); // 30 sec
});
function checkIdleTime() {
var diff = new Date().getTime() - lastActiveTime;
if (diff > 120000) { // 2 min of inactivity
window.location.href = "/logout?msg=onTimeOut";
} else {
$.ajax({url: '/refreshSession', error: function(data, status, xhr) {
alert("cannot refresh session on server: " + xhr);
window.location.reload();
}});
}
}
</script>
</head>
<h2>Employee page</h2>
<div>User: <%= request.getAttribute("user")%> </div>
<br/>
<a href='/logout'>Logout</a>
</body>
</html>
运行和测试
将上述代码部署到Tomcat服务器上,通过访问http://localhost:8080/
并输入有效的用户名和密码,可以测试会话自动延长的功能。如果用户在2分钟内没有任何操作,将会被自动登出并重定向到登录页面。
结论
通过上述步骤,我们可以实现一个在用户活跃时自动延长会话的Web应用。这种方法可以显著提高用户体验,避免因会话超时而频繁重新登录的问题。