有时候我们在做登录模块过程中难免会遇到这种问题,即使我们给用户进行了多重判断,比如:用户名,管理员,验证码,一系列的判断… 你是否真正考虑到用户的体验,比如不能让用户在同一时间,同一个浏览器重复登录问题,同时也包括不同浏览器登录(异地登录)问题。 这些都是我们应该去考虑的。如果是用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); }这样子就可以把登录的用户信息清除掉,用户可去其他浏览器登录亦或是继续登录。其实,这些大多可以根据自己的需求而定,代码可以是固定的,但思想是活的。