如何通過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">&nbsp;&nbsp;碼:</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="提&nbsp;&nbsp;&nbsp;&nbsp;交" onMouseOver="this.style.backgroundColor='red';" onMouseOut="this.style.backgroundColor='';" class="button" onClick="check()">&nbsp;&nbsp;&nbsp;&nbsp;   
<input name="" type="reset" value="重&nbsp;&nbsp;&nbsp;&nbsp;置" onMouseOver="this.style.backgroundColor='red';" onMouseOut="this.style.backgroundColor='';" class="button">  
</td>      
</tr>  
</table>  
</form>  
VerifyLogin類處理請求:
Java代碼
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);   }  

?

轉載于:https://www.cnblogs.com/lr393993507/p/5231395.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/272292.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/272292.shtml
英文地址,請注明出處:http://en.pswp.cn/news/272292.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Syncd - 開源自動化部署工具

官網地址&#xff1a;https://gitee.com/dreamans/syncd/issues syncd是一款開源的代碼部署工具&#xff0c;它具有簡單、高效、易用等特點&#xff0c;可以提高團隊的工作效率. 目前只支持類Linux系統. 特性 Go語言開發&#xff0c;編譯簡單、運行高效 Web界面訪問&#xff0…

嵌入式C語言基礎(二)

指針是分類型的&#xff1a; 指針根據類型不同&#xff0c;偏移值也不同。指針和數組&#xff0c;如何讓指針指向數組&#xff1f; ①用數組名 &#xff1a;int array[10],int* p,parray ②用第一個元素的地址&#xff1a;int array[10],int* p,p&array[0] 注意&#xff1a…

Linus中幫助命令man

使用方法&#xff1a;man 可以查看想要使用命令的詳細使用方法 man 命令

大牛是怎么思考設計SQL優化方案的?

作者&#xff1a;慘綠少年https://www.cnblogs.com/clsn/p/8214048.html在進行MySQL的優化之前&#xff0c;必須要了解的就是MySQL的查詢過程&#xff0c;很多查詢優化工作實際上就是遵循一些原則&#xff0c;讓MySQL的優化器能夠按照預想的合理方式運行而已。圖-MySQL查詢過程…

嵌入式C語言基礎(三)

字符串的定義方式及輸出&#xff1a; #include <stdio.h> #include <stdlib.h> void strPrint(char* data,int size) {int i;for(i0;i<size;i){printf("函數打印數組&#xff1a;%c\n",*data);}putchar(\n); } int main() {int i0;int a[3]{1,2,3};c…

web.config配置數據庫連接

第一種&#xff1a;獲取連接字符串 首先要定義命名空間 system.configuration 1. string connstr string constr ConfigurationManager.AppSettings["connstring"]; web.config文件:加在<appsettings>和</appsettings> 之間 <appsettings> <a…

用 Git 和 Github 提高效率的 10 個技巧!

Git 和 GitHub 都是非常強大的工具。即使你已經使用他們很長時間&#xff0c;你也很有可能不知道每個細節。我整理了 Git 和 GitHub 可能提高日常效率的10個常用技巧。GitHub1、快捷鍵: t 和 w在你的源碼瀏覽頁面&#xff0c;按 t 可以快速進入模糊文件名搜索模式&#xff1a;在…

docker顯示鏡像的摘要信息

顯示鏡像的摘要信息 docker images --digests

嵌入式C語言基礎(四)

為什么要用結構體&#xff1f; 在實際問題中&#xff0c;一組數據往往具有不同的數據類型。例如&#xff0c;在學生登記表中&#xff0c;姓名應為字符型;學號可為整型或字符型&#xff1b;年齡應為整型&#xff1b;性別應為字符型&#xff1b;成績可為整型或實型。顯然不能用一…

命令行分析java線程CPU占用

1.使用top命令找出占用cpu最高的JAVA進程pid號 2. 找出占用cpu最高的線程&#xff1a; top -Hp pid -d 1 -n 1 3. 打印占CPU最高JAVA進程pid的堆棧信息 jstack pid > /tmp/stacktrace.log 4. 把占CPU最高線程號碼換算成16進制到stacktrace.log中尋找相應線程16進制值找到…

docker搜索鏡像

docker search 要下載的 OFFICIAL 為ok的表示是官方鏡像

C#操作HttpClient工具類庫

using System; using System.Collections.Generic; using System.Net.Http; using System.Windows.Forms; using System.Configuration; using System.IO; using Newtonsoft.Json; namespace Dcflow { public class HttpHelper { //獲取Configuration對象 public static string…

docker從倉庫找鏡像

docker search -s 數量 要下載的 數量表示倉庫start數

bzoj 1911: [Apio2010]特別行動隊 2011-12-26

1911: [Apio2010]特別行動隊 Time Limit: 4 Sec Memory Limit: 64 MBSubmit: 892 Solved: 359[Submit][Status][Discuss] DescriptionInputOutputSample Input4 -1 10 -20 2 2 3 4 Sample Output9HINT Source _________________________________________ 很簡單的動規方程&a…

嵌入式C語言基礎鏈表

什么是鏈表&#xff1f; 鏈表其實就是一種數據結構&#xff0c;所謂的數據結構就是數據存放的思想。 數組、鏈表優缺點&#xff1a; 增加一個元素或者刪除一個元素都很難&#xff0c;因為地址是連續的&#xff0c;刪除一個元素可能會挪動多個元素&#xff0c;不靈活。但是對于鏈…

docker pull 從倉庫拉取鏡像

docker pull 要拉取的鏡像名 等價于 docker pull 要拉取的鏡像名:lastest 拉取固定的鏡像&#xff1a;docker pull 要拉取的鏡像名:版本號 省略lastest表設計就是拉取的最新的

理解js中的原型鏈,prototype與__proto__的關系

說到prototype&#xff0c;就不得不先說下new的過程。 我們先看看這樣一段代碼&#xff1a; 1<script type"text/javascript">2 var Person function () { };3 var p new Person();4</script>很簡單的一段代碼&#xff0c;我們來看看這個new究竟做了什…

C#抓取網頁HTML內容

using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Net; using System.Text; using System.IO; using System.Text.RegularExpressions; namespace Web { /// <summary> /// 公共方法類 /// </summary> p…

項目一感應垃圾桶(Wemos)

硬件材料&#xff1a; Wemos D1、SG90舵機、HC-SR04、杜邦線若干、蜂鳴器3.3V&#xff08;可有可無&#xff09; 軟件材料&#xff1a; arduino IDE編譯器、USB轉串口驅動 Wemos D1&#xff1a; 特性&#xff1a; 基于ESP-8266EX及arduino做的一個融合arduino兼容&#xff0…