如何通過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程式碼- <form action="verifyLogin.do" method="post" name="form">
- <table>
- <tr align="center">
- <td colspan="6" align="left">
- <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>
- </fieldset>
- </td>
- </tr>
- <tr>
- <td align="right">使用者名稱:</td>
- <td><input type="text" name="name" style="{ width: 100px;height: 15px;}" ></td>
- <td align="right">密 碼:</td>
- <td><input type="password" name="pwd" style="{ width: 100px;height: 15px;}"></td>
- <td>
- <%-- <select name="authority" size="1">--%>
- <%-- <option value="11">管理員</option>--%>
- <%-- <option value="00">普通使用者</option>--%>
- <%-- </select>--%>
- <input type="hidden" name="authority" value="11" >
- </td>
- </tr>
- <tr align="center">
- <td colspan="6" align="center">
- <input name="" type="button" value="提 交"
- onMouseOver="this.style.backgroundColor='red';"
- onMouseOut="this.style.backgroundColor='';" class="button"
- onClick="check()">
- <input name="" type="reset" value="重 置"
- onMouseOver="this.style.backgroundColor='red';"
- onMouseOut="this.style.backgroundColor='';" class="button">
- </td>
- </tr>
- </table>
- </form>
- String name=request.getParameter("name");
- String pwd=request.getParameter("pwd");
- String ip = request.getRemoteHost();
- //String Ip=request.getRemoteAddr();
- User user=UserHelp.getUserByName(name);
- String err="";
- if(user!=null){
- if (user.getPwd().equals(pwd)){
- //out.println("驗證成功!");
- boolean flag = true;
- List<HttpSession> sessions = (List<HttpSession>)application.getAttribute("sessionlist");
- for(int i = 0;i<sessions.size();i++){
- HttpSession ses = null;
- try{
- ses = sessions.get(i);
- User usr = (User)ses.getAttribute("user");
- String cuip = (String)ses.getAttribute("remoteHost");
- if(null!=usr&&usr.getName().equals(user.getName())&&!ip.equals(cuip)){//login repeatly!
- flag = false;
- err="<center><font color='red'>對不起該使用者已經有人登入,您不能重複登入!</font></center><br><br>";
- out.println(err);
- break;
- }
- }catch(Exception e){
- sessions.remove(i);
- }
- }
- if(flag){
- session.setAttribute("user",user);
- session.setAttribute("remoteHost",ip);
- sessions.add(session);
- application.setAttribute("sessionlist",sessions);
- }
- if(flag&&user.getAuthority().equals("11")){
- response.sendRedirect("manageFrames2.htm");
- }
- if(flag&&user.getAuthority().equals("00")){
- response.sendRedirect("manageFrames1.htm");
- }
- }
- else{
- err="<center>密碼錯誤,請重新登入!</center><br><br>";
- out.println(err);
- }
- }
- else{
- err="<center>無此使用者,請重新登入!</center><br><br>";
- out.println(err);
- }