java限制在同一臺電腦上只允許有一個用戶登錄系統

在web應用系統中,出于安全性考慮,經常需要對同一客戶端登錄的用戶數量和一個客戶同時在多個客戶端登陸進行限制。

具體一點就是:

1、在同一臺電腦上一次只允許有一個用戶登錄系統;

2、一個用戶在同一時間只允許在一個客戶端登錄。

我最近做的一個系統就遇到了這樣的問題,本來系統已經開發完成了,但是安全測評沒有通過,就是因為沒有做這兩個限制。怎么來做這樣的限制呢?我在網上找了很久,發現問這個問題的人很多,但是沒有找到特別清楚的答案。后來自己摸索著,看了一些書,終于找到解決辦法了。

要解決這個問題實際上不難,對于高手來說可能都懶得去說了,但是對于不熟悉web編程的人來說可能會困擾很久。下面我把我的解決辦法說出來,供大家參考!

先介紹一下我那個系統的背景:j2ee,tomcat,沒有用cookie。

首先確定解決這兩個問題的基本思路:

1、要解決同一臺電腦上只允許有一個用戶登錄系統,只有一個辦法。監視每一個連接的來源,如果發現有一個新的連接與某個已經存在的連接來自同一臺電腦,則終止其中的一個(當然,也可以提醒用戶,讓他自己決定終止哪一個)。

2、要禁止一個用戶賬號同時在不同的客戶端登錄,只有監視每一個連接的用戶賬號,如果發現一個新連接的用戶賬號跟某個已經存在的連接的用戶賬號相同,則自動將前一個終止(同樣,也可以讓用戶自己決定終止哪一個)。

確定了基本思路以后,就要找具體辦法了。我最初的想法是在數據庫建立一張表,存放已登錄用戶的用戶名、物理地址、Session id等信息。當用戶登錄時,與這張表里面的數據進行匹配,如果發現物理地址與表中的某條記錄相同,則表示是同一臺客戶端上有多個用戶再登錄,如果發現正在登錄的用戶的用戶名與表中已有記錄相同而主機名不同,則表示是一個賬號同時在不同的客戶端使用。

相信很多一開始遇到這個問題的人都會考慮這種解決辦法。但是這種辦法有很多問題,最主要的問題有兩個:第一是效率,每一次都要從數據庫里面取數據進行匹配。第二是用戶退出時需要刪除表中的記錄,而當用戶非正常退出時,很難及時監測(后來發現其實有辦法監測)。

后來在網上的某個帖子里面看到一位大俠提到用監聽器,只是那位大俠說的太含糊,照他說的辦法根本無法解決。雖然無法解決,但是提供了一個思路。于是我找了一本書,仔細看了其中關于監聽器的部分。解決辦法就在其中了!!!

監聽器的詳細介紹見我的下一篇博文,這里先把解決辦法告訴大家:

監聽器可以監聽Session及其所包含的屬性,即Attribute。

所以我們要做的就是:

1、建立一個監聽器,實現HttpSessionAttributeListener接口,監聽每一個Attribute的增加、編輯、刪除事件。監聽器中還要建立一個map,將所有的session放入這個map中。

2、在用戶登錄時將用戶名、物理地址、Session id存到Session中去(可以建立一個用戶登錄地址數據傳輸對象,我建立了一個UserSessionAdd類,里面包含username,macAdd,sessionId三個屬性,用戶登錄時將這個數據對象初始化,并存入到session中)。

3、每個新會話開啟時,在監聽器中對Session包含的屬性進行判斷,如果新增的屬性與map中已有session的用戶登錄地址數據相同,則表示新會話與我們要做的兩個限制相沖突。將與之沖突的會話提取出來,銷毀掉!

這么說,還是不夠清楚,下面看代碼:

Web.xml文件:
03.<listener>  
04.  
05.       <listener-class>監聽器類的路徑,如:com.web.MyListener</ listener-class >  
06.  
07.</listener>  


用戶登錄地址數據傳輸對象:

01.public class UserSessionAdd {  
02.  
03.  
04.private Stringadd;  
05.  
06.  
07.private Stringsessid;  
08.  
09.  
10.private String username  
11.  
12.public String getUsername(){  
13.  
14.return username  
15.  
16.}  
17.  
18.Public void setUsername(String username){  
19.  
20.       this.username=username;  
21.  
22.    }  
23.  
24.public String getIp() {  
25.  
26.returnadd;  
27.  
28.}  
29.  
30.publicvoid setAdd(String add) {  
31.  
32.this.add = add;  
33.  
34.}  
35.  
36.public String getSessid() {  
37.  
38.returnsessid;  
39.  
40.}  
41.  
42.publicvoid setSessid(String sessid) {  
43.  
44.this.sessid = sessid;  
45.  
46.}  
47.  
48.  
49.}  

用戶登錄的代碼:

03.String userHost = request.getRemoteHost();  
04.  
05.String sessionId = request.getSession().getId();  
06.  
07.UserSessionAdd usa = new UserSessionAdd();  
08.  
09.usa.setUsername(username);  
10.  
11.usa.setSessid(sessionId);  
12.  
13.usa.setAdd(userHost);  
14.  
15.request.getSession().setAttribute(“usa”,usa);  


監聽器代碼:

01.publicclass MyListenerimplementsHttpSessionAttributeListener{  
02.  
03.  
04.Map<String, HttpSession> map =new HashMap<String, HttpSession>();  
05.  
06.publicvoidattributeAdded(HttpSessionBindingEvent event) {  
07.  
08.String name = event.getName();  
09.  
10.if(name.equals("usa")){  
11.  
12.UserSessionAdd usa = (UserSessionAdd)event.getValue();  
13.  
14.if(map.get(usa.getAdd())!=null){  
15.  
16.HttpSession sess = map.get(usa.getAdd());  
17.  
18.UserSessionAdd usa1 = (UserSessionAdd)sess.getAttribute("usa");  
19.  
20.sess.removeAttribute("usa");  
21.  
22.sess.invalidate();  
23.  
24.}  
25.  
26.map.put(usa.getAdd(), event.getSession());  
27.  
28.}  
29.  
30.}  
31.  
32.  
33.publicvoidattributeRemoved(HttpSessionBindingEvent event) {  
34.  
35.String name = event.getName();  
36.  
37.if(name.equals("usa")){  
38.  
39.UserSessionAdd usa = (UserSessionAdd)event.getValue();  
40.  
41.map.remove(usa.getAdd());  
42.  
43.}  
44.  
45.}  
46.  
47.  
48.publicvoidattributeReplaced(HttpSessionBindingEvent event) {  
49.  
50.// TODO Auto-generated method stub  
51.  
52.````  
53.  
54.}  
55.  
56.}  


轉自:http://blog.csdn.net/yutan_313/article/details/5405934


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

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

相關文章

Matplotlib——繪制圖表

文章目錄通過figure()函數創建畫布通過subplot()函數創建單個子圖通過subplots()函數創建多個子圖通過add_subplot()方法添加和選中子圖添加各類標簽繪制常見圖表繪制直方圖——hist()函數繪制散點圖——scatter()函數繪制柱狀圖——bar()函數設定線條的相關參數本地保存圖片通…

限制在同一臺電腦上只允許有一個用戶登錄系統

在web應用系統中&#xff0c;出于安全性考慮&#xff0c;經常需要對同一客戶端登錄的用戶數量和一個客戶同時在多個客戶端登陸進行限制。 具體一點就是&#xff1a; 1、在同一臺電腦上一次只允許有一個用戶登錄系統&#xff1b; 2、一個用戶在同一時間只允許在一個客戶端登錄…

Seaborn——繪制統計圖形

文章目錄可視化數據的分布繪制單變量分布繪制雙變量分布繪制成對的雙變量分布用分類數據繪圖類別散點圖通過stripplot()函數畫散點圖swarmplot()函數類別內的數據分布繪制箱型圖繪制提琴圖類別內的統計估計繪制條形圖繪制點圖可視化數據的分布 繪制單變量分布 一般采用最簡單…

Bokeh——交互式可視化庫

文章目錄前言如何通過Plotting繪制圖形前言 Bokeh是一個專門針對Web瀏覽器使用的交互式可視化庫&#xff0c;這是與其他可視化庫相比最核心的區別。 如何通過Plotting繪制圖形 Plotting是以構建視覺符號為核心的接口&#xff0c;可以結合各種視覺元素&#xff08;例如&#x…

指針、引用以及const限定符、constexpr限定符

文章目錄復合類型引用概念與使用引用的定義注意指針概念聲明方式取地址符指針值空指針利用指針訪問對象賦值和指針void* 指針指向指針的指針指向指針的引用初始化所有指針有多重含義的某些符號const限定符概念const的引用指針和const頂層const和底層constconstexpr和常量表達式…

關鍵字typedef、關鍵字using、auto類型說明符和declytpe類型指示符

文章目錄類型別名概念關鍵字 typedef別名聲明 (alias declaration) using指針、常量和類型別名類型別名簡化多維數組指針auto類型說明符概念復合類型、常量和autodecltype類型指示符概念decltype和引用類型別名 概念 有兩種方法可用于定義類型別名。 關鍵字 typedef typede…

初始化、賦值、默認初始化、列表初始化、類內初始值、直接初始化與拷貝初始化

文章目錄初始化和賦值的區別什么是默認初始化&#xff1f;列表初始化列表初始化的使用場景不適合使用列表初始化的場景類內初始值混用string對象和C風格字符串數組與vector對象關于vector對象兩者間的初始化關系直接初始化與拷貝初始化初始化和賦值的區別 初始化的含義是創建變…

js動態增加,刪除td,tr,table,div

js實現的動態添加&#xff0c;刪除table內容&#xff1a; 截圖如下&#xff1a; 1. 2. 源代碼&#xff1a; main.css body {background-image: url(../images/qiantai/bg.png);font-family: arial;font-size: 12px;color: #d4d7da;text-align: center;background-repeat: r…

string類的相關知識及部分操作

文章目錄string對象的初始化string::size_type類型string對象的讀寫操作使用標準庫中的iostream使用getline讀取一整行string對象的比較操作string對象的相加操作兩個string對象相加字面值和string對象相加string對象的初始化 拷貝初始化(copy initialization)&#xff1a;使用…

數組的部分練習

3.27&#xff1a;假設txt_size是一個無參數的函數&#xff0c;它的返回值是int。請回答下列哪個定義是非法的&#xff1f;為什么&#xff1f; unsigned buf_size1024; &#xff08;a&#xff09;int ia[buf_size];  &#xff08;b&#xff09;int ia[4*7-14]; &#xff08…

關于范圍for語句的使用

文章目錄使用范圍for語句處理多維數組使用范圍for語句處理多維數組 舉個例子&#xff0c;使用范圍for語句輸出多維數組&#xff08;ia&#xff09;所有值&#xff1a; for (const auto &row : ia)for (auto col : row)cout << col << endl;本循環中并沒有任何…

vector的應用練習

文章目錄編寫一段程序&#xff0c;使用條件運算符從vector< int >中找出哪些元素的值是奇數&#xff0c;然后將奇數值翻倍。 #include <iostream> #include <ctime> #include <vector> using namespace std; typedef int int_array[4]; int main() {v…

sizeof運算符運算結果小匯

文章目錄sizeof運算符的結果部分地依賴于其作用的類型sizeof運算符的結果部分地依賴于其作用的類型 對char或者類型為char的表達式執行sizeof運算&#xff0c;結果得1對引用類型執行sizeof運算得到被引用對象所占空間的大小對指針執行sizeof運算得到指針本身所占空間的大小對解…

jQuery實現復選框的全選和反選:

jQuery實現復選框的全選和反選&#xff1a; 截圖如下&#xff1a; 代碼如下&#xff1a; index.jsp: <% page language"java" import"java.util.*" pageEncoding"UTF-8"%> <%String path request.getContextPath();String basePath…

C語言隱式/顯式類型轉換 | C++四種強制類型轉換、類的隱式轉換、explicit

文章目錄C語言類型轉換隱式類型轉換顯式類型轉換C 強制類型轉換static_castreinterpret_castconst_castdynamic_cast類的隱式類型轉換概念只允許一步類類型轉換explicit 抑制構造函數定義地隱式轉換可以通過顯式轉換使用explicit構造函數C語言類型轉換 隱式類型轉換 編譯器在…

string對象和C風格字符串

混用string對象和C風格字符串 我們都知道允許使用字符串字面值來初始化string對象&#xff1a; string s("Hello World!");C規定&#xff0c;任何出現字符串字面值的地方都可以用以空字符結束的字符數組來替代&#xff1a; 允許使用以空字符結束的字符數組來初始化…

函數重載、引用再探、內聯函數

文章目錄函數重載為什么C支持重載&#xff0c;C語言不支持呢&#xff1f;extern “C”引用再探引用的特性引用的使用場景引用和指針引用和指針的不同點:內聯函數什么是內聯函數&#xff1f;內聯函數的特性內聯函數的好處類的內聯成員函數的聲明內聯函數的使用constexpr函數概念…

類的概念、成員函數的定義方式、類的訪問控制和封裝、類的大小、this指針

文章目錄類的概念structclassclass和struct的區別是什么呢&#xff1f;類中成員函數的兩種定義方式聲明和定義都在類中聲明和定義分離類的訪問控制和封裝類的封裝特性類的大小結構體內存對齊規則類的存儲方式this指針類的概念 在C中&#xff0c;類可以說是最重要的東西&#x…

jQuery實現兩個列表框的值之間的互換:

jQuery實現兩個列表框的值之間的互換&#xff1a; 截圖如下&#xff1a; 代碼如下&#xff1a; <% page language"java" import"java.util.*" pageEncoding"UTF-8"%> <%String path request.getContextPath();String basePath reque…

類的6個默認成員函數:構造函數、析構函數、拷貝構造函數、重載運算符、三/五法則

文章目錄6個默認成員函數構造函數概念默認構造函數的類型默認實參概念默認實參的使用默認實參聲明全局變量作為默認實參某些類不能依賴于編譯器合成的默認構造函數第一個原因第二個原因第三個原因構造函數初始化構造函數里面的“”是初始化嗎&#xff1f;為什么要使用列表初始化…