一直以為 限制一個賬號同時只能一個人登錄 就是單點登錄,經過網上查詢,一個賬號同一時間只能一個人登錄和單點登錄根本不是一回事。
解決思路:
- 在數據庫中創建一個內存表member_sessionid(即數據庫存儲引擎為membory),包含兩個字段(MS_ID,MS_SESSIONID)。其中MS_SESSIONID用來存儲 sessionId。注意:將主鍵id不要設置成自增的方式。
- 在創建用戶的時候,在內存表member_sessionid中添加一條數據,字段id為新建用戶在用戶表中的主鍵id,字段MS_SESSIONID先設為空
- 在用戶登錄成功之后,根據用戶id 去內存表查詢該用戶在內存表中的記錄,如果該記錄存在,將該記錄的MS_SESSIONID字段設置成 sessionId,如果不存在,在表中添加一條記錄,MS_ID設置成用戶的id,MS_SESSIONID設置為當前請求的sessionId.
- 添加一個攔截器,每次請求服務器時(這里不包括(登錄請求、退出請求以及靜態資源的請求)),根據用戶id去內存表中查詢用戶的記錄並取出該記錄的MS_SESSIONID字段
- 從請求中取出sessionId,和上面查出來的MS_SESSIONID字段進行對比,如果不相等,執行退出操作。
邏輯與代碼:
- 在數據庫創建一個表
CREATE TABLE `member_sessionid` ( `MS_ID` int(11) DEFAULT NULL COMMENT '用戶的id', `MS_SESSIONID` varchar(255) DEFAULT NULL COMMENT '用戶登陸的sessionId' ) ENGINE=MEMORY DEFAULT CHARSET=latin1
- 添加用戶的時候在內存表中添加一條記錄(其實本步驟可以省略)
i=adminService.add(admin); MemberSessionid memberSessionid = new MemberSessionid(admin.getId(), ""); j=memberSessionidService.insert(memberSessionid);
- 用戶登錄以后,根據判斷去維護member_sessionid表
String id = session.getAttribute("id").toString();//用戶的id MemberSessionid mSessionid =sessionService.selectById(Integer.parseInt(id)); if(mSessionid==null){ mSessionid=new MemberSessionid(Integer.parseInt(id), request.getSession().getId()); sessionService.insert(mSessionid); }else{ mSessionid.setMsSessionid(request.getSession().getId()); sessionService.update(mSessionid); }
- 添加攔截器並配置攔截器
public class SessionIdInterceptor implements HandlerInterceptor{ @Autowired private MemberSessionidService memberSessionidService; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // TODO Auto-generated method stub String sessionId =request.getSession().getId(); String userId = request.getSession().getAttribute("id").toString(); MemberSessionid memberSessionid=memberSessionidService.selectById(Integer.parseInt(userId)); // System.out.println(request.getRequestURI()); // System.out.println(request.getContextPath()); if(sessionId.equals(memberSessionid.getMsSessionid())){ return true; }else{ response.sendRedirect(request.getContextPath()+"/admin/reloadRemind"); return false; } } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // TODO Auto-generated method stub } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // TODO Auto-generated method stub } }
//在攔截器配置列表中添加新的攔截器的配置 <mvc:interceptor> <mvc:mapping path="/**" /> <mvc:exclude-mapping path="/admin/verifyCode" /> <mvc:exclude-mapping path="/admin/passwordCode" /> <mvc:exclude-mapping path="/admin/login" /> <mvc:exclude-mapping path="/js/**" /> <mvc:exclude-mapping path="/img/**" /> <mvc:exclude-mapping path="/css/**" /> <mvc:exclude-mapping path="/fonts/**" /> <mvc:exclude-mapping path="/upload/**" /> <mvc:exclude-mapping path="/resource/**" /> <mvc:exclude-mapping path="admin/welcomePage" /> <mvc:exclude-mapping path="/admin/reloadRemind" /> <mvc:exclude-mapping path="/admin/quit" /> <bean id="SessionIdInterceptor" class="net.sahv.cskg.interceptor.SessionIdInterceptor" > </bean> </mvc:interceptor>
這樣當用兩個瀏覽器先后用同一個賬號登錄的時候, 前一次登錄會因為后一次的登錄而退出登錄