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