如何做到同一個賬號同一時段只能登入一個
在許多web專案中,需要禁止使用者重複登入。一般來說有兩種做法:
一是在使用者表中維護一個欄位isOnLine(是否線上),使用者登入時,設定值為true,使用者退出時設定為false,在重複登入時,檢索到該欄位為true時,禁止使用者登入。這種方法有明顯的漏洞,及使用者在非正常情況退出(關閉瀏覽器、關機等)是,該欄位值一直為true,會導致使用者無法登入。
而另一種比較通用的做法是使用session監聽,重複登入後,強制之前登入的session過期,從而踢出了該使用者。具體做法是:使用監聽器維護伺服器上快取的sessionMap,該map是以<session.getId(),session>的鍵值對,在登入後,使用userid替換session.getId(),從而使得sessionMap中維護的是<userid, session>的鍵值對。後續該帳號重複登入時,檢索到已有該帳號session則強制它過期。
1、web.xml中配置session監聽
- <listener>
- <listener-class>com.cnpc.framework.listener.SessionListener</listener-class>
- </listener>
2、session監聽SessionListener類
- package com.cnpc.framework.listener;
- import javax.servlet.http.HttpSessionEvent;
-
import javax.servlet.http.HttpSessionListener;
- import com.cnpc.framework.utils.SessionContext;
- public class SessionListener implements HttpSessionListener {
- public static SessionContext sessionContext=SessionContext.getInstance();
- public void sessionCreated(HttpSessionEvent httpSessionEvent) {
-
sessionContext.AddSession(httpSessionEvent.getSession());
- }
- public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
- sessionContext.DelSession(httpSessionEvent.getSession());
- }
- }
- package com.cnpc.framework.utils;
- import java.util.HashMap;
- import javax.servlet.http.HttpSession;
- public class SessionContext {
- private static SessionContext instance;
- private HashMap<String,HttpSession> sessionMap;
- private SessionContext() {
- sessionMap = new HashMap<String,HttpSession>();
- }
- public static SessionContext getInstance() {
- if (instance == null) {
- instance = new SessionContext();
- }
- return instance;
- }
- public synchronized void AddSession(HttpSession session) {
- if (session != null) {
- sessionMap.put(session.getId(), session);
- }
- }
- public synchronized void DelSession(HttpSession session) {
- if (session != null) {
- sessionMap.remove(session.getId());
- if(session.getAttribute("userid")!=null){
- sessionMap.remove(session.getAttribute("userid").toString());
- //session.invalidate();
- }
- }
- }
- public synchronized HttpSession getSession(String session_id) {
- if (session_id == null) return null;
- return (HttpSession) sessionMap.get(session_id);
- }
- public HashMap getSessionMap() {
- return sessionMap;
- }
- public void setMymap(HashMap sessionMap) {
- this.sessionMap = sessionMap;
- }
- }
3、使用者登入成功後,更新session Map,如重複登入,強制之前session過期
- public void sessionHandlerByCacheMap(HttpSession session){
- String userid=session.getAttribute("userid").toString();
- if(SessionListener.sessionContext.getSessionMap().get(userid)!=null){
- HttpSession userSession=(HttpSession)SessionListener.sessionContext.getSessionMap().get(userid);
- //登出線上使用者
- userSession.invalidate();
- SessionListener.sessionContext.getSessionMap().remove(userid);
- //清除線上使用者後,更新map,替換map sessionid
- SessionListener.sessionContext.getSessionMap().remove(session.getId());
- SessionListener.sessionContext.getSessionMap().put(userid,session);
- }
- else
- {
- // 根據當前sessionid 取session物件。 更新map key=使用者名稱 value=session物件 刪除map
- SessionListener.sessionContext.getSessionMap().get(session.getId());
- SessionListener.sessionContext.getSessionMap().put(userid,SessionListener.sessionContext.getSessionMap().get(session.getId()));
- SessionListener.sessionContext.getSessionMap().remove(session.getId());
- }
- }
4、spring MVC攔截器校驗session是否過期,如果過期,給出提示,並跳轉到登入介面。
攔截器配置
web.xml配置
- <init-param>
- <description>Spring MVC配置檔案</description>
- <param-name>contextConfigLocation</param-name>
- <param-value>classpath:controller.xml</param-value>
- </init-param>
- <mvc:interceptors>
- <beanclass="com.cnpc.framework.interceptor.AuthInterceptor"/>
- </mvc:interceptors>
攔截器authInterceptor
- package com.cnpc.framework.interceptor;
- import java.io.PrintWriter;
- import java.util.Map;
- import javax.annotation.Resource;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import org.springframework.stereotype.Component;
- import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;
- import com.cnpc.framework.common.SessionContainer;
- @Component("SpringMVCInterceptor")
- public class AuthInterceptor extends HandlerInterceptorAdapter {
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
- request.setCharacterEncoding("UTF-8");
- response.setCharacterEncoding("UTF-8");
- response.setContentType("text/html;charset=UTF-8");
- //過濾登入、退出訪問
- String[] noFilters = new String[] { "/auth/login", "/auth/logout" };
- String uri = request.getRequestURI();
- boolean beFilter = true;
- for (String s : noFilters) {
- if (uri.indexOf(s) != -1) {
- beFilter = false;
- break;
- }
- }
- SessionContainer sessionContainer = (SessionContainer) request.getSession().getAttribute("SessionContainer");
- if (beFilter) {
- if (null == sessionContainer) {
- //ajax方式互動
- if (request.getHeader("x-requested-with") != null
- && request.getHeader("x-requested-with").equalsIgnoreCase("XMLHttpRequest"))// 如果是ajax請求響應頭會有,x-requested-with;
- {
- response.setHeader("sessionstatus", "timeout");// 在響應頭設定session狀態
- return false;
- }
- // 未登入
- PrintWriter out = response.getWriter();
- StringBuilder builder = new StringBuilder();
- builder.append("<scripttype=\"text/javascript\" charset=\"UTF-8\">");
- builder.append("alert(\"頁面過期,請重新登入\");");
- builder.append("window.top.location.href='/auth/logout';");
- builder.append("</script>");
- out.print(builder.toString());
- out.close();
- return false;
- } else {
- // 新增系統日誌
- // -----------------------------------
- // -----------------------------------
- }
- }
- Map paramsMap = request.getParameterMap();
- return super.preHandle(request, response, handler);
- }
- }
以上Sprring MVC攔截器在同伺服器以ajax方式互動時,前臺需做如下相應處理:
- //控制ajax請求,session超時處理頁面跳轉
- $.ajaxSetup({
-
contentType:"application/x-www-form-urlencoded;charset=
相關推薦
如何做到同一個賬號同一時段只能登入一個
在許多web專案中,需要禁止使用者重複登入。一般來說有兩種做法: 一是在使用者表中維護一個欄位isOnLine(是否線上),使用者登入時,設定值為true,使用者退出時設定為false,在重複登入時,檢索到該欄位為true時,禁止使用者登入。這種方法
shiro 實現單使用者登入,一個使用者同一時刻只能在一個地方登入
如果我們跟shiro的原始碼,我們可以看到。當用戶登入成功後,shiro會把使用者名稱放到session的attribute中,key為DefaultSubjectContext_PRINCIPALS_SESSION_KEY,這個key的定義是在shiro的org.ap
既然CPU同一時間只能執行一個執行緒,為什麼存在併發問題
一點小疑惑終於解開啦 1.CPU的時間是按時間片分的,而不是一個時間點,併發問題是由於CPU執行緒切換導致的。 現在假設有一段程式碼 if(i == 1) { i++; //斷點1 system.out.print(i); } //斷點2 有兩個執
mvc 簡單實現一個賬號只能在一個地方登入
1.在mvc專案中找到 Global.asax //保證同一次會話的SessionID 不變 protected void Session_Start(object sender, EventArgs e) { } pro
php 實現同一個賬號同時只能一個人登入
有點類似QQ,二臺電腦登入,一臺會把另一臺擠掉線,並提示其他地點登入資訊。一,實現原理1,使用者在電腦A登入,session資訊存放在redis當中,並將session_id存到mysql資料庫中。2,同一使用者在電腦B登入,驗證完使用者名稱和密碼後,將該使用者資訊從資料庫讀出,取得使用者在電腦A登入的ses
java web開發一個帳號同一時間只能一個人登入(單點登入)
對於一個帳號在同一時間只能一個人登入,可以通過下面的方法實現: 1 .在使用者登入時,把使用者新增到一個ArrayList中 2 .再次登入時檢視ArrayList中有沒有該使用者,如果ArrayList中已經存在該使用者,則阻止其登入 3 .當用戶退出時,需要從該ArrayList中刪除該使用者,這又分為
Springboot + redis+shiro 限制 同一賬號 同時 多處登入
從網上看了很多解決方案,用的最多的 應當是SessionId 了。方案雖多,適合自己的才是最好的。 之前做了一個 線上使用者的統計 和 管理員 踢出啟用線上使用者的功能,因此我得到了一個啟發。程式是死的,人是活得,我可不可以定一些規則,讓程式 根據我的規定 來 執行。 思路: 1.定
SpringMvc實現一個賬號只能在一個地方登陸,其他地方強制下線
一. 前言 在處理專案登入問題的時候,為了賬號的安全性以及資訊的同步性,有時我們需要做到同一個賬戶只允許在一處地方登入,如果一個賬戶在一個處地方登入之後,之後在另一個地方也使用同一個賬戶登入,則前一個登入的賬戶就強制下線; 做到這種效果的方式有很多種,比如使
jfinal+H5的websocket 實現同一賬戶在不同地點不同電腦只能登陸一個(互相踢下線)
公司專案需求,因為專案是開賬戶賣錢的,為了避免有的使用者開一個賬戶N個人用,所以要求A賬戶只能在一個地點登入,別人如果使用A賬戶在別的電腦或者地點登入後就會吧上一個人給踢下線,當然也可以讓後一個登入的人登入不了,這都是看你邏輯怎麼控制的。 效果類似是qq登入的效果,先來張
.NET預設一個客戶端對同一個伺服器地址同時只能建立2個TCP連線
做一個客戶端的測試小程式測試web service的併發處理。開始用async task做,不管建立多少個task,用netstat看同時只有兩個tcp連線。以為是async task的問題,改用BackgroundWorker和多執行緒都是同樣的問題,經google得知原來是.NET預設一個客戶端對同一個伺
我的shiro之旅: 十二 shiro 踢出使用者(同一使用者只能一處登入)
部落格已移至 http://blog.gogl.top 看了一下官網,沒有找到關於如何控制同一使用者只能一處登入的介紹,網上也沒有找到相關的文章。可能有些人會記錄使用者的登入資訊,然後達到踢出使用者的效果。這裡介紹一個更簡單的方法。 如果我們跟shiro的原始碼,我們可以
Spring Boot + Spring Security 防止使用者在多處同時登入(一個使用者同時只能登入一次)及原始碼分析
網上很多文章的實現方法寫得比較複雜 這裡介紹一個簡單的方法。 實現 @Configuration @EnableWebSecurity public class SecurityConfiguration extends WebSecurityConfig
VS2015 報“包含在 Image 和 Image 項組中。專案項不允許這樣做,它只能屬於一個項組。”解決方法
今天在開啟同事移交的VS2015專案時報錯:包含在 Image 和 Image 項組中。專案項不允許這樣做,它只能屬於一個項組。 百度了一下沒有找到解決方法。 也許是錯誤太低階,大神們都不願意記錄了。 解決方案: 1、根據VS的錯誤提示,找到
redis實現session共享,解決一個賬號只能在一個終端登陸
一個賬號在a電腦登陸了,此時在b電腦登陸,就會將a踢下線,需要解決兩個問題: 一、確保賬號只能在一個地方登陸; 二、登陸後傳送訊息通知; 對於第一個問題,我們可以藉助於session儲存於redis之後,實現session在多個站點,多臺伺服器共享的情況下,統一通過sess
執行這些代碼, Edit1只能輸入數字,小數點和負號,負號和小數點只能輸入一個,負號必須在最前,粘貼的數字必須完全正確.
eat win method and length use double .text sel 執行這些代碼, Edit1只能輸入數字,小數點和負號,負號和小數點只能輸入一個,負號必須在最前,粘貼的數字必須完全正確. type TForm1 = class(T
一個JAVA類文件中只能有一個public類嗎?
資料 pri blog 外部 title java get cnblogs bsp 測試代碼一: 1 public class Test { 2 public static void main(String[] args) { 3 4 }
解決session只能被一個瀏覽器訪問的問題
set coo jsession prot name 題解 朝向 不同的 etc 做購物車的時候,我們都知道購買的東西會保存到session中,但是光這樣簡單的保存起來就會帶來一個問題,只能呢被同一個瀏覽器訪問到,如果用戶使用不同的瀏覽器進行訪問網頁的話肯定是會出問題的。下
Android ListView中的item只能有一個選中的問題和ListView與activity互動的問題
Android中ListView中的item與activity的互動有幾種方式:可以用回撥,廣播等,下面的方式是動態廣播的方式 ListView中的item選中事件,比如有多個item,每個item中都有一個CheckBox,我們要只選擇其中的一個,這是我們需要給每個item設定一
Python實現指令碼鎖功能,同時只能執行一個指令碼
1. 檔案鎖 指令碼啟動前檢查特定檔案是否存在,不存在就啟動並新建檔案,指令碼結束後刪掉特定檔案。 通過檔案的判斷來確定指令碼是否正在執行。 方法實現也比較簡單,這裡以python指令碼為例 #coding=utf-8 # # 檔案鎖指令碼測試 # import os
php設計單例模式,一次只能產生一個物件
單例即單個物件,一次只能生產一個物件,程式碼如下 class Single{ // 定義一個類 static private $instance=null; // 宣告一個靜態屬性,因為靜態屬性的資料具有長期性 且僅能為類所呼叫 所以這個靜態屬性用來儲存物件。