Java防止用户同一时间重复登录(包括异地登录)

有时候我们在做登录模块过程中难免会遇到这种问题,即使我们给用户进行了多重判断,比如:用户名,管理员,验证码,一系列的判断… 你是否真正考虑到用户的体验,比如不能让用户在同一时间,同一个浏览器重复登录问题,同时也包括不同浏览器登录(异地登录)问题。
这些都是我们应该去考虑的。如果是用Spring 框架的话,Spring security 是可以实现防止用户重复登录的问题的,但我这里并没有用到框架,因为我这里不需要做太高的限制。

我们可以利用 Servlet三大域对象 request、session、application(ServletContext)中的ServletContext,它是一个全局的储存信息的空间,服务器启动后就被创建,服务器停止后才销毁。
request,一个用户可有多个;session,一个用户一个;而servletContext,所有用户共用一个。所以,为了节省空间,提高效率,ServletContext中,要放必须的、重要的、所有用户需要共享的线程又是安全的一些信息。
思路:我们将用户的登录信息保存在context里, 然后利用监听器HttpSessionListener监听每一个登录用户的登录情况,实时监控session。

Servlet:

/*登录方法*/
public void login(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException{
		String username = request.getParameter("username");//登录名
		String password = request.getParameter("password");//密码
		HttpSession session=request.getSession();
		response.setCharacterEncoding("UTF-8");
		PrintWriter out=response.getWriter();
		SystemUsertable usertable = service.login(username);//SystemUsertable 自己封装存放用户信息的类
		if (usertable != null) {
			if (usertable.getPassword().equals(password)) {
				session.setAttribute("userid", usertable.getUserid());
				session.setAttribute("username", usertable.getUsername());
			} else {
				out.write("<html><head><meta charset='utf-8'></head><script>alert('密码错误');window.location.href='../jsp/login.jsp';</script>");
			}
		}else {
			out.write("<html><head><meta charset='utf-8'></head><script>alert('用户不存在');window.location.href='../jsp/login.jsp';</script>");
		}
		ServletContext context = session.getServletContext();
		@SuppressWarnings("unchecked")
		Map<String, Object> loginMap = (Map<String, Object>) context.getAttribute("loginMap");
		if (loginMap == null) {
		    loginMap = new HashMap<String, Object>();
		}
		for (String key : loginMap.keySet()) {
			int result=usertable.getUserid();
			String day = "";
			day = String.valueOf(result);
			
		    if (day.equals(key)) {
			    if (session.getId().equals(loginMap.get(key))) {
			    	out.write("<html><head><meta charset='utf-8'></head><script>alert('在同一地点重复登录');window.location.href='../jsp/login.jsp';</script>");
			    } else {
			    	out.write("<html><head><meta charset='utf-8'></head><script>alert('异地已登录,请先退出登录');window.location.href='../jsp/login.jsp';</script>");
			    }
		    }else{
		    }
		}
		loginMap.put(String.valueOf(usertable.getUserid()),session.getId());
		context.setAttribute("loginMap", loginMap);
		// 将用户保存在session当中
		session.setAttribute("usertable", usertable);
		// session 销毁时间
		session.setMaxInactiveInterval(10*60);
		out.write("<html><head><meta charset='utf-8'></head><script>alert('登录成功');window.location.href='../jsp/main.jsp';</script>");
	}

这时候我们需要写一个监听器,监听每一个登录用户的登录情况。首先去web.xml 配置监听器:

/*监听器存放路径*/
<listener>  
	    <listener-class>  
	       com.day.listener.SessionListener
	    </listener-class>  
</listener>

Listener:

/*监听器*/
public class SessionListener implements HttpSessionListener  {
	@Override
	public void sessionCreated(HttpSessionEvent httpSessionEvent) {//创建
		// TODO Auto-generated method stub
	}
	@Override
	public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {//销毁
		// TODO Auto-generated method stub
		HttpSession session = httpSessionEvent.getSession();
		SystemUsertable user = (SystemUsertable) session.getAttribute("usertable");
		if (user != null) {
			ServletContext application = session.getServletContext();
			@SuppressWarnings("unchecked")
			Map<String, Object> loginMap = (Map<String, Object>) application.getAttribute("loginMap");
			loginMap.remove(user.getUserid());
			application.setAttribute("loginMap", loginMap);
			session.removeAttribute("usertable");
		}
	}
}

最后需要对它的退出登录进行处理,退出时销毁session, 清除用户登录信息。

 /*退出登录*/
public void loginOut(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException{
	HttpSession session = request.getSession();
	String id = session.getId();
	if (session != null) {
		try {
			session.removeAttribute("usertable");
			String user= id; 
			if (session.getAttribute(user) != null) {
				session.removeAttribute(user);
			}
			ServletContext context = session.getServletContext();
			@SuppressWarnings("unchecked")
			Map<String, Object> loginMap = (Map<String, Object>) context.getAttribute("loginMap");
			if (loginMap != null) {
			    loginMap = new HashMap<String, Object>();
			}
			context.setAttribute("loginMap", loginMap);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	request.getRequestDispatcher("/jsp/login.jsp").forward(request, response);
}

这样子就可以把登录的用户信息清除掉,用户可去其他浏览器登录亦或是继续登录。其实,这些大多可以根据自己的需求而定,代码可以是固定的,但思想是活的。

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实现用户长时间不操作就退出登录的方法可以通过以下步骤来实现: 1. 获取用户的最后一次操作时间,可以通过记录用户最后一次操作时间戳或者会话的最后访问时间来实现。 2. 设置一个时间阈值,比如说30分钟,如果当前时间减去用户最后一次操作时间大于等于这个时间阈值,则认为用户长时间没有操作,需要退出登录。 3. 在用户每次操作时,更新用户的最后一次操作时间。 4. 可以使用定时器或者线程来实现定时检查用户的最后一次操作时间,如果超过时间阈值则强制退出登录。 下面是一个 Java 实现的示例代码: ```java import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class UserSession { private long lastAccessTime; private Timer timer; public UserSession() { lastAccessTime = new Date().getTime(); timer = new Timer(); timer.schedule(new TimeoutTask(), 30*60*1000); // 设置30分钟的超时时间 } public void access() { lastAccessTime = new Date().getTime(); } public void cancel() { timer.cancel(); } class TimeoutTask extends TimerTask { @Override public void run() { long currentTime = new Date().getTime(); if (currentTime - lastAccessTime >= 30*60*1000) { // 如果超时则退出登录 cancel(); // 执行退出登录操作 } } } } ``` 在每次用户访问时,调用 `access()` 方法更新最后一次访问时间,在用户退出登录时,调用 `cancel()` 方法取消定时器任务。当超时时,定时器任务会自动执行 `run()` 方法,检查最后一次访问时间是否超过指定的阈值,如果超过则执行退出登录操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值