Session管理之超時設置和強制下線


(一)Session超時時間設置的三種方式:

    (1)在web.xml中設置session-config

<session-config> <session-timeout>2</session-timeout> </session-config>

    即交互間隔時間最長為2分鍾(該處時間單位為分鍾),2分鍾后session.getAttribute()獲取的值為空。

    (2)在Tomcat的/conf/web.xml中session-config,默認值為:30分鍾

<session-config> <session-timeout>30</session-timeout> </session-config>

   時間單位為分鍾。

    (3)在Servlet中設置

HttpSession session = request.getSession();
session.setMaxInactiveInterval(60);

  該處時間單位為秒

  優先級:Servlet中設置 >web.xml設置 > Tomcat/conf/web.xml設置


 

(二)同一用戶強制下線

    大家都知道在目前很多的web項目中,大多數情況下都是可以讓同一個用戶賬號在不同的登錄入口登錄的,但這樣其實就顯得不是很嚴謹了,畢竟信息修改等操作對於信息是否能完全即時同步還是個未知之數。所以,接下來,我要做的只是對於不同瀏覽器的同一個用戶賬號的強制下線處理,對於同一個瀏覽器暫不做考慮,先來看下面這張圖。大概的了解一下:

    從上面可以看出:同一個瀏覽器對於不同的賬號,登錄時會產生相同的sessionId,這也就導致了用戶之間信息的覆蓋;不同瀏覽器對於不同的賬號登錄時,登錄時會產生不同的sessionId,這也就給了我們可操作的空間了,正是要利用這一點來進行判斷和相應處理。

    (1)添加監聽器

    為了方便這里使用Session監控的方式,創建SessionListener,如下:

public class SessionListener implements HttpSessionBindingListener{ @Override public void valueBound(HttpSessionBindingEvent event){ // TODO Auto-generated method stub } @Override public void valueUnbound(HttpSessionBindingEvent event){ // TODO Auto-generated method stub } }

    這里HttpSessionBindingListener和HttpSessionListener效果一樣,大家可以任選其一。重載兩個方法:session的創建和銷毀。

    當然,在web.xml中添加相應配置是必不可少的:

<listener> <listener-class>com.yoki.util.SessionListener</listener-class> </listener>

    由於sessionId和userId需要存儲,方便后面的判斷,我們在上面的類中添加兩個Map,如下:

//保存username和session的映射 public static HashMap<String,Session> MAP1 = new HashMap<String,Session>(); //保存sessionID和username的映射 public static HashMap MAP2 = new HashMap();

    最后,用戶登錄驗證成功時需要調用一個方法來判斷是否強制下線:

public static void userLogin(Session session,String sUserName){ //已登錄 if(MAP2.containsValue(sUserName)){ Session l_session = MAP1.get(sUserName); //不同瀏覽器,同一用戶(強制下線前一個) if(l_session != null && l_session.getId() != session.getId()){ MAP1.remove(sUserName); MAP2.remove(l_session.getId()); l_session.setAttribute("msg", "您的賬號已在另一處登錄!"); MAP2.put(session.getId(), sUserName); MAP1.put(sUserName, session); } //同一瀏覽器,同一用戶(不做任何變動) }else{ //未登錄 if(MAP2.containsKey(session.getId())){ //同一瀏覽器,不同用戶(不做任何變動) }else{ //不同瀏覽器,不同用戶(正常添加) MAP2.put(session.getId(), sUserName); MAP1.put(sUserName, session); } } }

    解釋一下:這里使用username和userId效果一樣,看你們怎么方便怎么用了,方法中的邏輯是根據上面的圖來編寫的,首先判斷用戶是否登錄了,因為MAP中保存了相關的session關聯信息,所以可以通過這個來判斷;由於此處只對不同瀏覽器相同用戶進行處理,所以直接判斷是否是同一個瀏覽器。方法的參數session是用戶在當前瀏覽器登錄時的信息,我們可以從MAP中得到之前保存過的相同用戶的session信息,與之進行比較,里面的邏輯是:移除MAP中保存的之前的用戶信息(對應的session此時未銷毀),並給其session添加一個msg信息(后面用到,往下看),再添加新的用戶信息。

    上面的方法調用放在登錄驗證成功后,各自項目不同,但登錄驗證的類基本差不多:

SessionListener.userLogin(session, USERNAME);

    (2)添加前端頁面調用的方法

    在登錄驗證的類中添加如下方法:

/* * 判斷用戶是否重復登錄 */ @RequestMapping(value="/checkUserOnline") @ResponseBody public void checkUserOnline(HttpServletRequest request,HttpServletResponse response) throws IOException{ HttpSession session=request.getSession(); PrintWriter out = response.getWriter(); String msg = ""; if(session.getAttribute("msg") != null){ msg = session.getAttribute("msg").toString(); System.out.println(msg); } out.print(session.getAttribute("msg")); }

    方法中獲取之前添加到session中的msg,用來判斷是否強制下線,繼續。

    (3)前端頁面循環調用

    選擇一個頁面,最好是所有頁面都用到的,比如我用的index.jsp,如下:

<script type="text/javascript"> $(document).ready(function(){ setInterval("checkUserOnline()",5000); //每隔5秒判斷一次 } function checkUserOnline(){ var msg = ""; $.ajax({ type : "POST", url : "checkUserOnline", data : {}, async: false, success : function(data){ msg = data; } }); if (msg == 'null' || msg == '' || msg == 'undefined'){ return; }else{ //調用你的注銷用戶方法 var url="<%=path%>/logout.do"; $.get(url,function(data){}); } } </script>

    js中調用setInterval方法,設置調用的方法和間隔時間,方法里通過ajax調用上面添加的類並返回msg,通過msg來判斷是否調用注銷方法(路徑啥的自己注意,能調用到就ok)。

    (4)注銷

    一般web項目登錄進去后都會有個退出按鈕,點擊即返回到登錄頁,此時在里面添加一行代碼,防止錯誤,可能會出現重新登錄報session已被銷毀的錯誤提示,但第二次便會成功,這里便是為了消除該錯誤:

SessionListener.MAP2.remove(session.getId());

   參考:https://my.oschina.net/u/3747963/blog/1787633


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM