如何通過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上場吧:
- <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);
- }