web项目中禁止用户重复登录。一般来说有两种做法:
一是在用户表中维护一个字段(是否在线),用户登录时,设定值为true,用户退出时设定为false,在重复登录时,检索到该字段为true时,禁止用户登录。这种方法有明显的漏洞,及用户在非正常情况退出(关闭浏览器、关机等)是,该字段值一直为true,会导致用户无法登录。
而另一种比较通用的做法是使用session监听,重复登录后,强制之前登录的session过期,从而踢出了该用户。
1.web.xml中配置session监听类
<listener> <listener-class>com.energy.ims.util.Session.SessionListener</listener-class> </listener> |
2.session监听的SessionListener
package com.energy.ims.util.Session; import javax.servlet.http.HttpSessionEvent; import javax.servlet.http.HttpSessionListener; 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()); } } |
3.SessionContex类(使用单例模式)
package com.energy.ims.util.Session; 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; } } |
4.用户登陆成功,取用户id作为sessionMap中的key,判断用户是否已经登陆;若未登陆,将userid和浏览器session保存到sessionMap中,若已经登陆,强制原SessionMap过期,替换value值。以此机制保证用户唯一登陆标识。
public xxxx xxxxxx(){ //执行登陆验证,登陆成功执行如下: session.setAttribute("userid", user.getId()); String userid=session.getAttribute("userid").toString();//判断,清除在线用户后,更新map,替换map中value的值(session) if(SessionListener.sessionContext.getSessionMap().get(userid)!=null){ SessionListener.sessionContext.getSessionMap().remove(userid); SessionListener.sessionContext.getSessionMap().remove(session.getId()); SessionListener.sessionContext.getSessionMap().put(userid,session); }else{ // 根据当前sessionid 取session对象。 更新map key=用户名 value=session对象 删除map SessionListener.sessionContext.getSessionMap().put(userid,session); SessionListener.sessionContext.getSessionMap().remove(session.getId()); } } |
.5.拦截器,(springMVC配置不进行叙述)
拦截器从session中取出用户信息,判断session未失效后,取出用户信息,获取服务器中sessionMap中的该用户对应value值(usersession),比较服务器中保存的用户登陆信息usersession同当前浏览器session是否一致,从而拦截跳转
//根据登陆用户,获取服务器中封装的sessionMap中的value值 HttpSession userSession=(HttpSession)SessionListener.sessionContext.getSessionMap().get(((SysUserinfoVO)sessionUser).getId() + ""); //服务器sessionMap中value值和浏览器session对比是否一致 if(userSession != session) { redirect(request, response); //封装的跳转方法,可自行定义跳转到登陆页面 return false; } |