1. 程式人生 > >如何通過session控制單點登入

如何通過session控制單點登入

  web伺服器為每一個瀏覽器例項對應一個session。

這個session有自己的一個獨立id,這個id儲存在瀏覽器的cookie中(這個cookie貌似隨著這個瀏覽器例項的關閉而清除),

訪問web伺服器的時候,web服務會根據你cookie中的sessionId來決定重新建立一個session還是使用已經存在的session。

如果使用桌面的ie圖示開啟一個IE視窗,這個視窗屬於一個新的瀏覽器例項(其中不包含sessionid資訊),

這時候用這個IE訪問web伺服器的時候web伺服器會為這個瀏覽器例項新建立一個httpsession,

sessionId也是新的(sessionId儲存到本地的cookie中),

不會對你以前開啟的視窗中的session產生覆蓋,關閉ie視窗的時候cookie中的資訊也就清除掉了。 

如果是在開啟的ie視窗中按“ctrl+n”開啟一個ie視窗,這個視窗於剛才的視窗是同一個例項,

與剛才的視窗共用session,所有的同一個ie例項的視窗都關掉後,會清除掉sessionId。

補充一點,可以通過人為的輸入引數sessionId通知web伺服器你使用的是哪個session(如果伺服器存在這個session的話)。


*****************************************************************************************************************************************


         單點登入(有別於SSO:Single Sign On),首先解釋一下對專案需求中的單點登入的理解:

一個使用者帳號成功登入後,在該次session還未失效之前,不能在其他機器上登入同一個帳號,

這有點類似與QQ只能在同一臺計算機上登入。好了,如何實現呢?現在分析一下:

一次登入也就是一次會話(Session),那麼我們可以很容易聯想到通過控制session來實現單點登入,

我的設想是這樣的,登入後將使用者資訊儲存到session中,如果此時在另外一臺機器上一個相同的帳號請求登入,

通過遍歷Web服務中所有session並判斷其中是否包含同樣的使用者資訊,通過這樣的判斷,

在另一臺機器上登入該帳號是不成功的。

上面已經提到了,需要通過控制session,對web服務中所有session進行遍歷操作,

那麼你肯定會想到application這個大物件了(當然你也可以採用快取或者資料庫),

具體實現方法是這樣的,首先在application中建立一個List<HttpSession>,

用來儲存每一次會話(session)物件,系統在驗證使用者登入請求時,通過遍歷該list並加以判斷,

最後決定是否讓該使用者成功登入。OK,需求和設計都在上面了,接下來就是編碼工作了哈。

不過在這裡還需要考慮幾個問題:

1、如果登入後關閉了瀏覽器,想立即開啟一個新的瀏覽器並登入將會失敗,

因為前一次登入後的session還沒銷燬,你需要等其銷燬後方可再次登入成功,

這種問題如何解決???哈哈,你是不是已經想到要用javascript處理一下下,

即在關閉瀏覽器的時候觸發一個事件,該事件就是通知來銷燬當前session的。

2、第二個問題其實是接上一個問題而討論的,用javascript觸發瀏覽器關閉事件並不是一個好辦法,

因為有很多因素可能導致這個事件觸發不成功,還有Firefox和IE這兩個東東意見有時候並不統一,

最後有一個比較可惡的問題就是,我在同一臺機器上不能開啟兩個瀏覽器視窗去登入相同的帳號,

因為一個瀏覽器對應一個session啊!這就是為什麼我在文章一開始要引用一些基本知識。

既然問題很嚴重,那就動腦殼去想辦法啊!我在這裡自言自語了半天,我不打算用中文繼續講下去了,

直接code上場吧:

login.jsp Html程式碼
  1. <form action="verifyLogin.do" method="post" name="form">  
  2. <table>  
  3. <tr align="center">  
  4. <td colspan="6" align="left">
  5. <fieldset STYLE='border:0;padding:14px;filter:glow(color=#0080ff,strength=3);letter-spacing:2px;'><font STYLE='font:12px/14px;color:#ffffff;font-weight:bold;'>請輸入帳號和密碼:</font>
  6. </fieldset>  
  7. </td>      
  8. </tr>  
  9. <tr>  
  10.     <td align="right">使用者名稱:</td>  
  11.     <td><input type="text"  name="name" style="{ width: 100px;height: 15px;}" ></td>  
  12.     <td align="right">密&nbsp;&nbsp;碼:</td>  
  13.     <td><input type="password" name="pwd" style="{ width: 100px;height: 15px;}"></td>  
  14.     <td>  
  15. <%--    <select name="authority" size="1">--%>  
  16. <%--      <option value="11">管理員</option>--%>  
  17. <%--      <option value="00">普通使用者</option>--%>  
  18. <%--    </select>--%>  
  19.      <input type="hidden" name="authority" value="11" >  
  20.     </td>  
  21. </tr>  
  22. <tr align="center">  
  23. <td colspan="6" align="center">  
  24. <input name="" type="button" value="提&nbsp;&nbsp;&nbsp;&nbsp;交" 
  25. onMouseOver="this.style.backgroundColor='red';" 
  26. onMouseOut="this.style.backgroundColor='';" class="button" 
  27. onClick="check()">&nbsp;&nbsp;&nbsp;&nbsp;   
  28. <input name="" type="reset" value="重&nbsp;&nbsp;&nbsp;&nbsp;置"
  29.  onMouseOver="this.style.backgroundColor='red';" 
  30. onMouseOut="this.style.backgroundColor='';" class="button">  
  31. </td>      
  32. </tr>  
  33. </table>  
  34. </form>  
  VerifyLogin類處理請求: Java程式碼
  1. String name=request.getParameter("name");   
  2.  String pwd=request.getParameter("pwd");   
  3.  String ip = request.getRemoteHost();   
  4.  //String Ip=request.getRemoteAddr();   
  5.  User user=UserHelp.getUserByName(name);   
  6.  String err="";   
  7.  if(user!=null){   
  8.      if (user.getPwd().equals(pwd)){   
  9.           //out.println("驗證成功!");   
  10.           boolean flag = true;   
  11.           List<HttpSession> sessions = (List<HttpSession>)application.getAttribute("sessionlist");   
  12.           for(int i = 0;i<sessions.size();i++){   
  13.             HttpSession ses = null;   
  14.             try{   
  15.                ses = sessions.get(i);   
  16.                User usr = (User)ses.getAttribute("user");   
  17.                String cuip = (String)ses.getAttribute("remoteHost");   
  18.                if(null!=usr&&usr.getName().equals(user.getName())&&!ip.equals(cuip)){//login repeatly!   
  19.                   flag = false;   
  20.                   err="<center><font color='red'>對不起該使用者已經有人登入,您不能重複登入!</font></center><br><br>";   
  21.                   out.println(err);   
  22.                   break;   
  23.                }   
  24.             }catch(Exception e){   
  25.                sessions.remove(i);   
  26.             }   
  27.           }   
  28.           if(flag){   
  29.               session.setAttribute("user",user);   
  30.               session.setAttribute("remoteHost",ip);   
  31.               sessions.add(session);   
  32.               application.setAttribute("sessionlist",sessions);   
  33.           }   
  34.          if(flag&&user.getAuthority().equals("11")){   
  35.             response.sendRedirect("manageFrames2.htm");   
  36.           }   
  37.          if(flag&&user.getAuthority().equals("00")){   
  38.             response.sendRedirect("manageFrames1.htm");   
  39.           }   
  40.      }   
  41.      else{   
  42.          err="<center>密碼錯誤,請重新登入!</center><br><br>";   
  43.           out.println(err);   
  44.      }   
  45.    }   
  46.  else{   
  47.    err="<center>無此使用者,請重新登入!</center><br><br>";     
  48.      out.println(err);   
  49.  }