Java 多用戶登陸限制的實現方法

Java 多用戶登陸限制的實現方法 如今有兩種解決方案: 一、將用戶的登陸信息用一個標誌位的字段保存起來,每次登陸成功就標記1,註銷登陸就標記爲0,當標記爲1的時候不容許別人登陸。 二、將用戶的登陸信息保存在application內置做用域內, 而後利用session監聽器監聽每個登陸用戶的登陸狀況。 很顯然,第一種方式 每次登陸 都須要操做數據庫,多了一些沒必要要的性能開銷,並且在登陸狀態下 萬一忽然電腦關閉了,那就永遠都不能登陸了,可用性比較低。 可是第二種方式就不同了,可操做性強,很方便維護全部在線用戶的信息。 接下來 主要介紹第二種方式的具體實現: 一、在處理登陸的login方法中,先查詢數據庫驗證下該用戶是否存在,若是存在 判斷該登陸帳戶是否已經鎖定了, 而後從application內置做用域對象中取出全部的登陸信息,查看該username帳戶是否已經登陸,若是登陸了,就友好提示下,反之表示能夠登陸,將該登陸信息以鍵值對的方式保存在application中。 代碼以下:javascript

//沒有使用零配置前 每一個訪問的方法都要加上@Action ,不然404 @Action(value="login", results={ @Result(name="index", location="index.jsp"), }) public String login() throws Exception { try{ User result = userService.login(user.getFuUserName(), user.getFuPassword()); if(result!=null){ if(result.getFuStatus()!=null && result.getFuStatus()==0){ super.setRequestAttr(Constant.MESSAGE, "抱歉,該用戶已被鎖定!"); return "error"; } Map<String, String> loginUserMap = (Map<String, String>) super.getApplicationAttr(Constant.LOGIN_USER_MAP); boolean isExist = false; String sessionId = super.getSessionId(false); if(loginUserMap==null){ loginUserMap = new HashMap<String, String>(); } for (String username : loginUserMap.keySet()) { //判斷是否已經保存該登陸用戶的信息 或者 若是是同一個用戶進行重複登陸那麼容許登陸 if(!username.equals(result.getFuUserName()) || loginUserMap.containsValue(sessionId)){ continue; } isExist = true; break; } if(isExist){ super.setRequestAttr(Constant.MESSAGE, "抱歉,該用戶已登陸!"); return "error"; }else { loginUserMap.put(result.getFuUserName(), sessionId); } //登陸成功 super.setSessionAttr(Constant.LOGIN_USER, result); super.setApplicationAttr(Constant.LOGIN_USER_MAP, loginUserMap); logger.info(result.getFuUserName() + " 登陸成功!"); //若是 session中fromUrl有值,就跳轉到該頁面 String fromUrl = (String)super.getSessionAttr(Constant.FROM_URL); if(fromUrl!=null){ super.setSessionAttr(Constant.FROM_URL, null); super.getResponse().sendRedirect(fromUrl.toString()); return null; } return "index"; } } catch (Exception e) { e.printStackTrace(); logger.info("登陸失敗: "+e.getMessage()); } super.setRequestAttr("message", "用戶名或密碼錯誤"); return "error"; } 二、登陸入口處理完以後,考慮到會話結束的話,那麼對應的登陸用戶也應該相應的註銷登陸。咱們能夠寫一個Session監聽器,監聽sessioon銷燬的時候,咱們將登陸的用戶註銷掉,也就是從application中移除。表示該用戶已經下線了。 代碼以下:html

package com.facelook.util; import java.util.Map; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; import org.apache.log4j.Logger; import com.facelook.entity.User; public class SessionListener implements HttpSessionListener{ private Logger logger = Logger.getLogger(this.getClass()); @Override public void sessionCreated(HttpSessionEvent event) { } @Override public void sessionDestroyed(HttpSessionEvent event) { //在session銷燬的時候 把loginUserMap中保存的鍵值對清除 User user = (User)event.getSession().getAttribute("loginUser"); if(user!=null){ Map<String, String> loginUserMap = (Map<String, String>)event.getSession().getServletContext().getAttribute("loginUserMap"); loginUserMap.remove(user.getFuUserName()); event.getSession().getServletContext().setAttribute("loginUserMap",loginUserMap); } } } web.xml中配置以下:java

<!-- session listener --> web

<listener> <listener-class>com.facelook.util.SessionListener</listener-class> </listener> 三、另外,還有一個問題,若是說登陸的用戶忽然關閉了瀏覽器或者頁面而沒有點擊退出按鈕。那麼能夠利用beforeunload 事件,在瀏覽器刷新或者關閉的時候觸發。ajax

//在刷新或關閉時調用的事件 $(window).bind('beforeunload',function(){ $.ajax({ url:"${ctx}/system/user/user!logout.action", type:"post", success:function(){ alert("您已退出登陸"); } }); ); 可是若是一些客觀緣由,好比電腦忽然關機,自動重啓,等等,這些就無法避免了,因此只能等待服務器端的session會話重置以後才能夠再登陸。 除非 作一個 統計全部在線人員的模塊,管理員在裏面進行在線人員的登陸登出的狀態管理,把那些有問題的登陸用戶直接銷燬掉。 接下來簡單介紹下在線人員模塊的管理: 一、首先須要一個session監聽器來監聽全部的回話create的狀況,這時候每次建立一個session就能夠count+1 ,而後銷燬的時候count-1 ,另外還須要一個ServletContext的監聽器來監聽web應用的生命週期,獲取servletContext對象,而後將在線人員總數統計出來存放進去; 具體代碼以下:數據庫

package com.facelook.util; import java.util.Map; import javax.servlet.ServletContext; import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; import org.apache.log4j.Logger; import com.facelook.entity.User; public class SessionListener implements HttpSessionListener,ServletContextListener{ private int count; private ServletContext servletContext = null; public SessionListener() { count = 0; } private Logger logger = Logger.getLogger(this.getClass()); @Override public void sessionCreated(HttpSessionEvent event) { count++; setContext(event); logger.info("***************the http session is created...***************"); } @Override public void sessionDestroyed(HttpSessionEvent event) { //在session銷燬的時候 把loginUserMap中保存的鍵值對清除 User user = (User)event.getSession().getAttribute("loginUser"); if(user!=null){ Map<String, String> loginUserMap = (Map<String, String>)event.getSession().getServletContext().getAttribute("loginUserMap"); loginUserMap.remove(user.getFuUserName()); event.getSession().getServletContext().setAttribute("loginUserMap",loginUserMap); } count--; setContext(event); logger.info("***************the http session is destroyed...***************"); } public void setContext(HttpSessionEvent httpSessionEvent){ httpSessionEvent.getSession().getServletContext().setAttribute("online", count); } @Override public void contextDestroyed(ServletContextEvent servletcontextevent) { this.servletContext = null; logger.info("***************the servlet context is destroyed...***************"); } @Override public void contextInitialized(ServletContextEvent servletcontextevent) { this.servletContext = servletcontextevent.getServletContext(); logger.info("***************the servlet context is initialized...***************"); } } 二、在UserAction中建立管理在線用戶的模塊的方法,而且支持強制退出的功能;apache

/** * 退出登陸瀏覽器

  • @return
  • @throws ServletException
  • @throws IOException / public String logout() throws ServletException, IOException{ try { Map<String, String> loginUserMap = (Map<String, String>) super.getApplicationAttr(Constant.LOGIN_USER_MAP); User user = (User) super.getSessionAttr(Constant.LOGIN_USER); super.removeAttribute(Constant.LOGIN_USER_MAP); loginUserMap.remove(user.getFuUserName()); super.setApplicationAttr(Constant.LOGIN_USER_MAP,loginUserMap); logger.info("退出登陸成功!"); } catch (Exception e) { e.printStackTrace(); logger.error("退出登陸失敗: "+e.getMessage()); } return INPUT; } /*
  • 在線用戶管理
  • @return / public String loginManager(){ return SUCCESS; } /*
  • 強制退出其餘用戶
  • @return */ public String logoutOther(){ try { String username = ServletActionContext.getRequest().getParameter("username"); Map<String, String> loginUserMap = (Map<String, String>) super.getApplicationAttr(Constant.LOGIN_USER_MAP); if(username!=null && loginUserMap.containsKey(username)){ loginUserMap.remove(username); super.setApplicationAttr(Constant.LOGIN_USER_MAP, loginUserMap); } } catch (Exception e) { e.printStackTrace(); logger.info("強制退出失敗: "+e.getMessage()); } return null; } 三、在管理頁面加載在線用戶的列表; 對應的方法定義完畢以後,而後再在對應的管理頁面添加在線列表,具體以下:

<%@page import="java.util.Map"%> <%@page import="java.util.Map.Entry"%> <%@ page language="java" pageEncoding="UTF-8" %> <%@ include file="/common/taglib.jsp" %>服務器

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> session

<html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>歡迎來到Facelook</title> <%@ include file="/common/resource.jsp" %> <script type="text/javascript"> <!-- //在刷新或關閉時調用的事件 $(window).bind('beforeunload',function(){ $.ajax({ url:"${ctx}/system/user/user!logout.action", type:"post", success:function(){ alert("您已退出登陸"); } }); }); function logout(username){ if(username=="${sessionScope.loginUser.fuUserName}"){ alert("不容許退出本身帳號!"); return; } $.ajax({ url:"${ctx}/system/user/user!logoutOther.action?username="+username, type:"post", success:function(){ $("#tr"+username).hide(); var count = parseInt($("#count").html()); $("#count").html(count-1); alert("退出成功!"); } }); } //--> </script> </head> <body> <%@ include file="/common/header.jsp" %> <div id="main" class="wrap"> <%@ include file="/common/lefter.jsp" %> <div class="righter"> <div class="main"> <h2>登陸列表</h2> <% Map<String,String> map = (Map<String,String>)application.getAttribute("loginUserMap"); out.println("目前共有<font id='count'>"+map.size()+"</font>個用戶在線!!"); %> <table border="1" width="400"> <%for(Entry<String,String> m : map.entrySet()){%> <tr id="tr<%=m.getKey()%>"> <td> <%=m.getKey()%> </td> <td width="80"> <a href="javascript:logout('<%=m.getKey()%>')">強制退出</a> </td> </tr> <%}%> </table> </div> </div> </div> <%@ include file="/common/footer.jsp" %> <%@ include file="/common/message.jsp" %> </body> </html> 好了啓動部署項目,而後啓動服務,進入在線用戶管理模塊,簡單效果以下圖:

須要注意的是:當前登陸用戶 不容許強制退出本身的登陸信息。 這樣子,基本上能夠實現防止多用戶登陸的案例了!

相關文章
相關標籤/搜索