限制在同一台電腦上只允許有一個使用者登入系統,有一個使用者登入
在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
<listener>
<listener-class>監聽器完整路徑</listener-class>
</listener>
使用者登入地址資料轉送對象:
public class UserSession {
private String addr;
private String sessid;
private String username;
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
public String getSessid() {
return sessid;
}
public void setSessid(String sessid) {
this.sessid = sessid;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
}
使用者登入的代碼:
HttpSession session = request.getSession();
String userHost = request.getRemoteHost();
String sessionId = request.getSession().getId();
UserSession userSession = new UserSession();
userSession.setUsername(user.getUsername());
userSession.setSessid(sessionId);
userSession.setAddr(userHost);
request.getSession().setAttribute("userSession",userSession);
監聽器代碼:
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpSession;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
public class LoginListenner implements HttpSessionAttributeListener {
Map<String, HttpSession> map = new HashMap<String, HttpSession>();
public void attributeAdded(HttpSessionBindingEvent event) {
String name = event.getName();
if (name.equals("userSession")) {
UserSession userSession = (UserSession) event.getValue();
if (map.get(userSession.getUsername()) != null) {
HttpSession session = map.get(userSession.getUsername());
session.removeAttribute("userSession");
session.invalidate();
}
map.put(userSession.getUsername(), event.getSession());
}
}
public void attributeRemoved(HttpSessionBindingEvent event) {
String name = event.getName();
if (name.equals("userSession")) {
UserSession userSession = (UserSession) event.getValue();
map.remove(userSession.getUsername());
}
}
public void attributeReplaced(HttpSessionBindingEvent event) {
// TODO Auto-generated method stub
}
}
JSP做網站 怎限制同一台電腦同一時間只有一個使用者登入
用電腦機器編碼來當作判斷使用者登入的標識.
同一個標識只能存在一個session.
類似QQ,登入兩個同樣號碼會有一個被迫下線一個道理.
asp可以不可以限制同一個使用者只可以在同一台電腦上登陸同網站
有三個方法解決,但實行起來都不怎麼好。
1、通過cookies記錄使用者登入狀態,伺服器產生一段校正碼存到用戶端的cookies裡,伺服器通過讀取用戶端cookie的值來得知是否第一次登入的網站。缺點是存不長久,一旦cookies失效或使用者刪除cookies或關閉cookies都無法再使用。
2、根據使用者IP判斷。這個效果好,但在中國不適行。國內上網使用者基本上都是ADSL撥號,每次串連都會換一個新的IP。不過在區域網路效果不錯。
3、寫個控制項安裝在用戶端,用戶端通過控制項發送用戶端機子的一些驗證資訊到伺服器,比如硬碟的序號。此項雖能很好的解決問題,但大凡網民都不願意裝個組件。