最近在帮朋友做一个购物网站,里面涉及到了登陆的问题。其中包括后台管理员的登陆和用户的登陆。
在这个网站中,设计了后台管理员单态登陆,即一个账号只能有一个登陆实例。很容易想到的就是用application实现,在application中放置一个hashmap,储存登陆的管理员信息。同时为了实现登陆超时,也在session中存放登陆对象,通过设置session的listener监控session的消亡,移除application中的对象。那么问题来了,如果用户因为断电或者任性,非法关闭了浏览器,再打开浏览器,显然application中还存在上一次的登陆对象,不能再次登陆了,这样就造成了用户永远无法登陆的问题。
在网上查了一下,很多人遇到这个问题,万能的网友给的建议是用心跳包的方式,判断用户离线,但是本人觉得这样方法太过占用资源。于是有了以下这个方法。核心思想是,利用cookie保存成功登陆的sessionId,然后在application对象再增加一个hashmap,key是sessionId,value依然是管理员对象。每次打开登陆界面时,首先检查cookie,如果存在就取出sessionId,然后查看application中保存sessionId的hashmap,如果存在这个sessionId,就取出管理员信息,并放在新的session中。
PS:浏览器的session机制是这样的,每次打开浏览器服务器会为这个浏览器创建一个新的session,它的消失不受浏览器的关闭控制。而是服务器自动回收,但是如果浏览器关闭再打开,就会产生一个新的session,但并不意味着服务器中找不到上一次打开浏览器的session。所以将sessionId保存在cookie中,相当于变相在浏览器中找到上一次的session并进行操作。
源代码如下
(1) session 监听器代码
- ServletContext application;
- @Override
- public void sessionCreated(HttpSessionEvent arg0)
- {
- ServletContext application=arg0.getSession().getServletContext();
- HashMap<String,ManagerForm>allManagerBySessionId=( HashMap<String,ManagerForm>)application.getAttribute("allManagerBySessionId");
- if (null==allManagerBySessionId)
- {
- allManagerBySessionId=new HashMap<String,ManagerForm>();
- application.setAttribute("allManagerBySessionId",allManagerBySessionId);
- }
- System.out.println("创建");
- }
- @SuppressWarnings("unchecked")
- @Override
- public void sessionDestroyed(HttpSessionEvent arg0)
- {
- ManagerForm form = (ManagerForm) arg0.getSession().getAttribute("user");
- application=arg0.getSession().getServletContext();
- HashMap<String, ManagerForm>hashMap=(HashMap<String, ManagerForm>)application.getAttribute("allManager");
- if (hashMap!=null)
- {
- if (null!= hashMap.remove(form.getId().toString()))
- {
- System.out.println("移除");
- }
- }
- HttpSession session=arg0.getSession();
- HashMap<String,ManagerForm>allManagerBySessionId=( HashMap<String,ManagerForm>)application.getAttribute("allManagerBySessionId");
- if (allManagerBySessionId.containsKey(session.getId()))
- {
- allManagerBySessionId.remove(session.getId());
- application.setAttribute("allManagerBySessionId",allManagerBySessionId);
- }
- }
(2)登陆校验页面代码
- //保存SesionID至浏览器cookie
- Cookie cookie=new Cookie("user",request.getSession().getId());
- cookie.setMaxAge(3600);
- response.addCookie(cookie);
- //向特定hashMap中保存form对象
- HashMap<String,ManagerForm>allManagerBySessionId=( HashMap<String,ManagerForm>)appliction.getAttribute("allManagerBySessionId");
- allManagerBySessionId.put(request.getSession().getId(),userForm);
(3) 浏览器登陆页面校验代码
-
- <%
- Cookie[] allCookies = request.getCookies();
- String savedSessionId = "";
- if (allCookies != null)
- {
- for (int i = 0; i < allCookies.length; i++)
- {
- if (allCookies[i].getName().equals("user"))
- {
- savedSessionId = allCookies[i].getValue();
- break;
- }
- }
- HashMap<String, ManagerForm> allManagerBySessionId = (HashMap<String, ManagerForm>) application
- .getAttribute("allManagerBySessionId");
- if (allManagerBySessionId.containsKey(savedSessionId))
- {
- ManagerForm form = allManagerBySessionId
- .get(savedSessionId);
- session.setAttribute("user", form);
- response.sendRedirect(request.getContextPath()+"/background/managerIndex.jsp");
- return;
- }
- }
- %>