日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

如何防止同一账号多次登录

發(fā)布時間:2025/3/20 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 如何防止同一账号多次登录 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

2019獨角獸企業(yè)重金招聘Python工程師標準>>>

如何限制同一客戶端登錄的用戶數(shù)量以及禁止同一用戶同時在不同客戶端登錄:

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

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

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

常見3種解決辦法:

1)通過數(shù)據(jù)庫狀態(tài)位判斷該用戶是否已經(jīng)登錄。

? ? ? ?首先在數(shù)據(jù)庫建立一張表,存放已登錄用戶的用戶名、物理地址、Session id等信息。當用戶登錄時,與這張表里面的數(shù)據(jù)進行匹配,如果發(fā)現(xiàn)物理地址與表中的某條記錄相同,則表示是同一臺客戶端上有多個用戶再登錄,如果發(fā)現(xiàn)正在登錄的用戶的用戶名與表中已有記錄相同而主機名不同,則表示是一個賬號同時在不同的客戶端使用。

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

2)利用緩存Cache方便地實現(xiàn)此功能

? ? ? ?Cache與Session這二個狀態(tài)對像的其中有一個不同之處,Cache是一個全局對象,作用的范圍是整個應用程序,所有用戶;
而Session是一個用戶會話對象,是局部對象,用于保存單個用戶的信息。?
只要把每次用戶登錄后的用戶信息存儲在Cache中,把Cache的Key名設為用戶的登錄名,Cache的過期時間設置為Session的超時時間,在用戶每次登錄的時候去判斷一下Cache[用戶名]是否有值,如果沒有值,證明該用戶沒有登錄,否則該用戶已登錄。

/// <summary> /// 防止多次登錄 /// </summary> /// <param name="sender"></param> /// <param name="e"></param>private void Button1_Click(object sender, System.EventArgs e) { string strUser = string.Empty; string strCacheKey = this.TextBox1.Text;strUser = Convert.ToString(Cache[strCacheKey]);if (strUser == string.Empty) { TimeSpan SessTimeOut = new TimeSpan(0, 0, System.Web.HttpContext.Current.Session.Timeout, 0, 0);Cache.Insert(strCacheKey, strCacheKey, null, DateTime.MaxValue, SessTimeOut, CacheItemPriority.NotRemovable, null); Session["User"] = strCacheKey; this.Label1.Text = Session["User"].ToString(); } else { this.Label1.Text = "這個用戶已經(jīng)登錄!"; } }

3)利用session監(jiān)聽器監(jiān)聽每一個登錄用戶的登錄情況。

簡潔版方法(c# 框架):

監(jiān)聽器可以監(jiān)聽Session及其所包含的屬性,即Attribute。

A.用戶登錄后,先去數(shù)據(jù)庫查詢該登錄名是否存在、是否鎖定。

? ? ? ?在登錄名存在且非鎖定的情況下,從application內(nèi)置作用域?qū)ο笾腥〕鏊械牡卿浶畔?#xff0c;查看該登錄名是否已經(jīng)登錄,如果登錄了,就友好提示下;反之表示可以登錄,將該登錄信息保存在application中。

主要代碼如下:

//所有的登錄信息 Map<String, String> loginUserMap = (Map<String, String>) super.getApplicationAttr(Constant.LOGIN_USER_MAP); boolean isExist = false; String sessionId = super.getSessionId(false); if(loginUserMap==null){ loginUserMap = new HashMap<String, String>(); } for (String username : loginUserMap.keySet()) { //判斷是否已經(jīng)保存該登錄用戶的信息,是否為同一個用戶進行重復登錄 if(!username.equals(user.getFuUserName()) || loginUserMap.containsValue(sessionId)){ continue; } isExist = true; break; } if(isExist){ //該用戶已登錄 // }else { //該用戶沒有登錄 loginUserMap.put(result.getFuUserName(), sessionId); // } //

B.登錄考慮完之后,考慮退出。
? ? ? 用戶正常退出時,我們需要將該用戶的登錄信息從session中移除。我們可以寫一個Session監(jiān)聽器,監(jiān)聽sessioon銷毀的時候,我們將登錄的用戶注銷掉,也就是從application中移除。表示該用戶已經(jīng)下線了。

// public void sessionDestroyed(HttpSessionEvent event) { // //在session銷毀的時候 把loginUserMap中保存的鍵值對清除 User user = (User)event.getSession().getAttribute("loginUser"); if(user!=null){ Map<String, String> loginUserMap = (Map<String, String>)event.getSession().getServletContext().getAttribute("loginUserMap"); loginUserMap.remove(user.getFuUserName()); event.getSession().getServletContext().setAttribute("loginUserMap",loginUserMap); } // } //

C.登錄的用戶突然關閉了瀏覽器,未點擊退出按鈕,情況,慮退出。

那么可以利用beforeunload 事件,在瀏覽器刷新或者關閉的時候觸發(fā)。

//在刷新或關閉時調(diào)用的事件 $(window).bind('beforeunload',function(){$.ajax({url:"${ctx}/system/user/user!logout.action",type:"post",success:function(){alert("您已退出登錄");}}); });

完整版方法(Java ee 開發(fā)框架):

1 ) 在登錄方法中加入如下兩行語句,作為程序的入口:

SessionListener.isAlreadyEnter(getHttpRequest().getSession(),this.getUserCode(),loginUser); getHttpRequest().getSession().setAttribute("isLoginIn", "LoginIn");

2)在SessionListener類中做相關的踢出處理:

import java.util.HashMap; import java.util.Iterator; import java.util.Map; import javax.servlet.ServletRequestEvent; import javax.servlet.ServletRequestListener; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionAttributeListener; import javax.servlet.http.HttpSessionBindingEvent; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; import org.apache.struts2.ServletActionContext; import com.hhwy.iepip.framework.message.Message; import com.opensymphony.xwork2.ActionContext; public class SessionListener implements HttpSessionListener,ServletRequestListener,HttpSessionAttributeListener{ public static Map<String, HttpSession> sessionMap = new HashMap<String, HttpSession>(); public static Map<String, HttpSession> sessionMap1 = new HashMap<String, HttpSession>(); private static Boolean onlyOne = Boolean.valueOf(Message.getMessage("session.onlyone")); private HttpServletRequest request ; //獲取request對象 public void requestInitialized(ServletRequestEvent event) { request = (HttpServletRequest)event.getServletRequest(); } //以下是實現(xiàn)HttpSessionListener中的方法:該方法登錄與否都會執(zhí)行 public void sessionCreated(HttpSessionEvent se){ } //以下是實現(xiàn)HttpSessionListener中的方法 public void sessionDestroyed(HttpSessionEvent se){ hUserName.remove(se.getSession().getId()); UserObject.remove(se.getSession().getId()); if(sessionMap!=null){ sessionMap.remove(se.getSession().getId()); } if(sessionMap1!=null){ sessionMap1.remove(se.getSession().getId()); } } /** * isAlreadyEnter-用于判斷用戶是否已經(jīng)登錄以及相應的處理方法 * <該方法是系統(tǒng)業(yè)務的方法,不是處理單個用戶登錄的問題,以該方法做為程序的入口> */ public static boolean isAlreadyEnter(HttpSession session,String sUserName,LoginUserInfo loginTriggers){ boolean flag = false; return flag; } /** * 此方法,可以在登錄時候添加一個session 用以判斷是否已經(jīng)登錄,然后再進行登錄人登錄控制 */ public void attributeAdded(HttpSessionBindingEvent event) { //如果只允許一個賬號一處登陸,單臺客戶端電腦只允許一個用戶登錄 if(onlyOne.booleanValue()){ String name = event.getName(); if(name.equals("isLoginIn")){ // 單臺客戶端電腦只允許一個用戶登錄 String ipAddr = this.getIpAddr(request); //如果原先已登錄,則踢出原先登陸的 if(sessionMap1.containsKey(ipAddr) ){ try{ sessionMap1.get(ipAddr).invalidate(); }catch(Exception e){} sessionMap1.remove(ipAddr); } if(ipAddr != null && event.getSession().isNew()) sessionMap1.put(ipAddr, event.getSession()); //只允許一個賬號一個客戶端登陸 String userName= getUserName(event); if(sessionMap.containsKey(userName) ){ try{ sessionMap.get(userName).invalidate(); }catch(Exception e){} sessionMap.remove(userName); } if(userName != null && event.getSession().isNew()) sessionMap.put(userName, event.getSession()); } } } public static String getIpAddr(HttpServletRequest request) { String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } //獲取session中存儲的用戶名private String getUserName(HttpSessionBindingEvent se) { String userName = null; return userName; } public void attributeRemoved(HttpSessionBindingEvent event) { // TODO Auto-generated method stub } public void attributeReplaced(HttpSessionBindingEvent arg0) { // TODO Auto-generated method stub } public void requestDestroyed(ServletRequestEvent arg0) { // TODO Auto-generated method stub } }

?

轉(zhuǎn)載于:https://my.oschina.net/u/3544533/blog/1796623

總結(jié)

以上是生活随笔為你收集整理的如何防止同一账号多次登录的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。