Java实现网页端session有效期的管理

网页前端请求服务器完成登录后,会获取一个session会话。session会有一个有效期,有效期过后服务器应该要告诉前端需要重新登录。如果在不同的浏览器登录,前者的会话也应该失效。本文将介绍如何实现这样的功能,包括"前端请求后端判断会话有效期JS代码"、“服务器后端拦截有用户请求代码”。

1、前端请求后端判断会话有效期JS代码。

前端使用了Layui前端框架,使用ajax请求后端。在调用ajax请求服务器时,首先判断session是否过期、有效:

$(document).ajaxComplete(function (event, xhr, settings) {
	console.log("监听到了");
	console.log(xhr);
	console.log(event)
	console.log(xhr.getResponseHeader("sessionStatus"));
	console.log("staffLoginUrl" + xhr.getResponseHeader("staffLoginUrl"));
	console.log("bxstaffLoginUrl=" + xhr.getResponseHeader("bxstaffLoginUrl"));
	layui.use('layer', function () {
		var layer = layui.layer;		//引用layui弹出层模块
		if (xhr.getResponseHeader("sessionStatus") == "timeOut") {
			if (xhr.getResponseHeader("staffLoginUrl")) {
				window.top.layer.alert('登录过期,请重新登录...', {
					cancel: function () {
						window.top.location.href = xhr.getResponseHeader("staffLoginUrl");
					}
				}, function (index) {
					window.top.location.href = xhr.getResponseHeader("staffLoginUrl");
					layer.close(index);
				});
			} else if (xhr.getResponseHeader("bxstaffLoginUrl")) {
				window.top.layer.alert('登录过期,请重新登录...', {
					cancel: function () {
						window.top.location.href = xhr.getResponseHeader("bxstaffLoginUrl");
					}
				}, function (index) {
					window.top.location.href = xhr.getResponseHeader("bxstaffLoginUrl");
					layer.close(index);
				});
			} else {
				window.top.layer.alert('请求超时请重新登陆 !', function (index) {
					layer.close(index);
				});
			}
		} else if (xhr.getResponseHeader("sessionStatus") == "duplicatedSession") {
			window.top.layer.alert('你已经在其它地方登录', {
				cancel: function () {
					window.top.location.href = xhr.getResponseHeader("staffLoginUrl");
				}
			}, function (index) {
				window.top.location.href = xhr.getResponseHeader("staffLoginUrl");
				console.log(xhr.getResponseHeader("staffLoginUrl"));
				layer.close(index);
			});
		}
	})
});

2、服务器后端拦截有用户请求代码。

新建StaffLoginInterceptor类,继承了Filter过滤器,这样用户的请求都将被StaffLoginInterceptor类所拦截。

从session中获取登录信息staff:

		/*
		 * 超时处理,ajax请求超时设置超时状态,页面请求超时则返回提示并重定向 session.getAttribute("")是获取到登录人的session信息
		 */
		Staff staff = (Staff) session.getAttribute(EnumSession.SESSION_Staff.toString());
如果	staff为null,说明用户未登录或登录已失效,此时需要告诉前端让用户重新登录
		if (staff == null && bxstaff == null && vip == null) {
			handleAnyOneLoginWithoutSession(request, response, httpRequest, httpResponse, session, loginUrl, staffLoginUrl, bxstaffLoginUrl, vipLoginUrl);
		}
		

	private void handleAnyOneLoginWithoutSession (ServletRequest request, ServletResponse response, HttpServletRequest httpRequest, HttpServletResponse httpResponse, HttpSession session, String loginUrl, String staffLoginUrl,
			String bxstaffLoginUrl, String vipLoginUrl) throws ServletException, IOException {
		logger.info("拦截到的URL=" + httpRequest.getRequestURL() + "	Cookie=" + httpRequest.getCookies() + "		SessionID=" + session.getId());
		// 判断是否为ajax请求
		if (httpRequest.getHeader("x-requested-with") != null && httpRequest.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest")) {
			httpResponse.addHeader("sessionStatus", "timeOut"); // 返回超时标识
			logger.info("url=" + loginUrl);
			// 判断当前登录的是哪个页面,跳转到相应的页面
			if (loginUrl.equals(staffLoginUrl)) {
				httpResponse.addHeader("staffLoginUrl", loginUrl);// 返回url
				httpRequest.getRequestDispatcher(staffLoginUrl).forward(request, response);
			} else if (loginUrl.equals(bxstaffLoginUrl)) {
				httpResponse.addHeader("bxstaffLoginUrl", bxstaffLoginUrl);// 返回url
				httpRequest.getRequestDispatcher(bxstaffLoginUrl).forward(request, response);
			} else if (loginUrl.equals(vipLoginUrl)) {
				httpResponse.addHeader("vipLoginUrl", vipLoginUrl);// 返回url
				httpRequest.getRequestDispatcher(vipLoginUrl).forward(request, response);
			}

			// chain.doFilter(request, response);// 不可少,否则请求会出错
		} else { // 非ajax请求,让其直接跳转到登录页面
			String str = "";
			if (session.getAttribute(EnumSession.SESSION_POS.toString()) == null) {
				str = "<script language='javascript'>" + "window.top.location.href='" + loginUrl + "';</script>";
				httpResponse.addHeader("sessionStatus", "timeOut"); // 返回超时标识
			}
			response.setContentType("text/html;charset=UTF-8");
			try {
				PrintWriter writer = response.getWriter();
				writer.write(str);
				writer.flush();
				writer.close();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}	

如果session不为null,说明已经用户已经登录过,判断session是否有效(有可能是不同浏览器传来的session)。

关键方法为needToIntercept,返回true则说明session无效,用户需重新登录:

			if (loginGuard.needToIntercept(company.getSN(), staff.getID(), posID, session)) {
				String str = null;
				if (posID == BaseAction.INVALID_POS_ID) { // 这是网页端上的操作
					// 判断是否为ajax请求
					if (httpRequest.getHeader("x-requested-with") != null) {
						httpResponse.addHeader("staffLoginUrl", loginUrl);// 返回url
						httpResponse.addHeader("sessionStatus", "duplicatedSession"); // 返回单点登录标识
						str = "<script language='window.top.location.href='" + loginUrl + "';</script>";// ......
					} else {
						str = "<script language='javascript'>alert('你已经在其它地方登录'); window.top.location.href='" + loginUrl + "';</script>";
					}
				} else { // 这是POS端上的操作
					Map<String, Object> params = new HashMap<String, Object>();
					params.put(BaseAction.JSON_ERROR_KEY, EnumErrorCode.EC_DuplicatedSession.toString());
					params.put(BaseAction.KEY_HTMLTable_Parameter_msg, "你已经在其它地方登录");
					str = JSONObject.fromObject(params, JsonUtil.jsonConfig).toString();
				}
				response.setContentType("text/html;charset=UTF-8");
				try {
					PrintWriter writer = response.getWriter();
					writer.write(str);
					writer.flush();
					writer.close();
				} catch (Exception e) {
					e.printStackTrace();
				}
				return false;
			}

needToIntercept方法主要是用了hashmap缓存了前端最新的已登录的用户session,所以只需要判断当前session与缓存中的session是否一致,即可判断出该session是否有效:

	public boolean needToIntercept(String companySN, int staffID, int posID, HttpSession session) {
		if ((posID != BaseAction.INVALID_POS_ID && posID <= 0) || staffID <= 0) {
			return true;
		}
		
		boolean needToIntercept = false;

		lock.writeLock().lock();

		LoginDevice currentLoginDevice = mapStaffLoginDevice.get(generateKey(companySN, staffID));
		if (currentLoginDevice != null) {
			if (posID == BaseAction.INVALID_POS_ID) {// 网页端登录
				if (currentLoginDevice.getClientSessionOfWeb().hashCode() != session.hashCode()) {
					needToIntercept = true;
				}
			} else {// POS机上登录
				if (currentLoginDevice.getPosIDOfPos() != posID) {
					needToIntercept = true;
				}
			}
		}

		lock.writeLock().unlock();
		
		return needToIntercept;
	}

 

posted @ 2021-12-22 16:47  Boxin-kim  阅读(81)  评论(0编辑  收藏  举报
Web Analytics
Guang Zhou Boxin