有時候我們在做登錄模塊過程中難免會遇到這種問題,即使我們給用戶進行了多重判斷,比如:用戶名,管理員,驗證碼,一系列的判斷… 你是否真正考慮到用戶的體驗,比如不能讓用戶在同一時間,同一個瀏覽器重復登錄問題,同時也包括不同瀏覽器登錄(異地登錄)問題。
這些都是我們應該去考慮的。如果是用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);
}
這樣子就可以把登錄的用戶信息清除掉,用戶可去其他瀏覽器登錄亦或是繼續登錄。其實,這些大多可以根據自己的需求而定,代碼可以是固定的,但思想是活的。