Spring 限制使用者重複登入
阿新 • • 發佈:2019-02-15
監聽器:
import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import javax.servlet.http.HttpSession; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; import xxxxx.TSUser; /** * * @author yuki_ho * */ public class SessionUserListener implements HttpSessionListener{ // key為sessionId,value為HttpSession,使用static,定義靜態變數,使之程式執行時,一直存在記憶體中。 private static Map<String, HttpSession> sessionMap = new HashMap<String, HttpSession>(500); /** * HttpSessionListener中的方法,在建立session */ @Override public void sessionCreated(HttpSessionEvent event) { // TODO Auto-generated method stub } /** * HttpSessionListener中的方法,回收session時,刪除sessionMap中對應的session */ @Override public void sessionDestroyed(HttpSessionEvent event) { getSessionMap().remove(event.getSession().getId()); } /** * 得到線上使用者會話集合 */ public static List<HttpSession> getUserSessions() { List<HttpSession> list = new ArrayList<HttpSession>(); Iterator<String> iterator = getSessionMapKeySetIt(); while (iterator.hasNext()) { String key = iterator.next(); HttpSession session = getSessionMap().get(key); list.add(session); } return list; } /** * 得到使用者對應會話map,key為使用者ID,value為會話ID */ public static Map<String, String> getUserSessionMap() { Map<String, String> map = new HashMap<String, String>(); Iterator<String> iter = getSessionMapKeySetIt(); while (iter.hasNext()) { String sessionId = iter.next(); HttpSession session = getSessionMap().get(sessionId); TSUser user = (TSUser) session.getAttribute("LOCAL_CLINET_USER"); if (user != null) { map.put(user.getId(), sessionId); } } return map; } /** * 移除使用者Session */ public synchronized static void removeUserSession(String userId) { Map<String, String> userSessionMap = getUserSessionMap(); if (userSessionMap.containsKey(userId)) { String sessionId = userSessionMap.get(userId); getSessionMap().get(sessionId).invalidate(); getSessionMap().remove(sessionId); } } /** * 增加使用者到session集合中 */ public static void addUserSession(HttpSession session) { getSessionMap().put(session.getId(), session); } /** * 移除一個session */ public static void removeSession(String sessionID) { getSessionMap().remove(sessionID); } public static boolean containsKey(String key) { return getSessionMap().containsKey(key); } /** * 判斷該使用者是否已重複登入,使用 * 同步方法,只允許一個執行緒進入,才好驗證是否重複登入 * @param user * @return */ public synchronized static boolean checkIfHasLogin(TSUser user) { Iterator<String> iter = getSessionMapKeySetIt(); while (iter.hasNext()) { String sessionId = iter.next(); HttpSession session = getSessionMap().get(sessionId); TSUser sessionuser = (TSUser) session.getAttribute("LOCAL_CLINET_USER"); // 這是你設定 儲存使用者對應session名 if (sessionuser != null) { if (sessionuser.getId().equals(user.getId())){ return true; } } } return false; } /** * 獲取線上的sessionMap */ public static Map<String, HttpSession> getSessionMap() { return sessionMap; } /** * 獲取線上sessionMap中的SessionId */ public static Iterator<String> getSessionMapKeySetIt() { return getSessionMap().keySet().iterator(); } }
web.xml:
<listener>
<listener-class>xxxxx.listener.SessionUserListener</listener-class>
</listener>
幫組類:
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpSession; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; public class ContextHolderUtils { /** * SpringMvc下獲取request * * @return */ public static HttpServletRequest getRequest() { HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); return request; } /** * SpringMvc下獲取session * * @return */ public static HttpSession getSession() { HttpSession session = getRequest().getSession(); return session; } }
服務類:(介面就忽略) -- 把前一個使用者剔除
import java.util.Map; import javax.servlet.http.HttpSession; import xxxxx.ContextHolderUtils; import xxxxx.TSUser; import org.springframework.stereotype.Service; import xxxxx.listener.SessionUserListener; import xxxxx.listener.service.SessionUserI; /** * * @author yuki_ho * */ @Service("sessionUser") public class SessionUserImpl implements SessionUserI{ /** * 登入時使用 -- 檢查是否重複登入並把線上的 替換成 自己 */ @Override public void changeLogin4Me(TSUser tsUser) { Boolean hasLogin = SessionUserListener.checkIfHasLogin(tsUser); HttpSession session = ContextHolderUtils.getSession(); if(hasLogin) SessionUserListener.removeUserSession(tsUser.getId()); SessionUserListener.addUserSession(session); } /** * 使用 攔截器時 -- 檢查是否當前 session使用者 */ @Override public Boolean checkLoginIsMe(TSUser tsUser) { if(null==tsUser) return false; Map<String,String> SessionUser= SessionUserListener.getUserSessionMap(); String curSession=SessionUser.get(tsUser.getId()); HttpSession session = ContextHolderUtils.getSession(); if(curSession.equals(session.getId())) return true; return false; } }
攔截器: -在controller前 攔截
Boolean flag =sessionUser.checkLoginIsMe(tsuer);
if(!flag) {
session.removeAttribute("LOCAL_CLINET_USER");
response.sendRedirect("loginController.do?login");
return false;
}
ps:請別在登入時攔截,在配置攔截器之前 排除登入攔截