项目中的多重登录检测处理
需求:
一个账户同时只能一次登录在线,当使用同一个账户二次登录的时候那么第一的登录将被失效(类似QQ挤下线)
处理基本思想:
将唯一用户ID与Session建立关联关系放在Application作用域中进行管理。
----------------------------------------------------------------------
关键处理类:
package com.defshare.sy.web.util;import java.util.HashMap;import java.util.Map;import java.util.Properties;import javax.servlet.ServletContext;import javax.servlet.http.HttpSession;import org.apache.log4j.Logger;import org.apache.struts2.ServletActionContext;import com.defshare.foundation.global.PropertiesUtil;import com.defshare.sy.config.AuthConfig;public final class AuthenUtil {static Logger LOG = Logger.getLogger(AuthenUtil.class);/** * 多重登录检测处理 * @param loginId */ public synchronized static final void multipleLoginDetect(String loginId){ServletContext servletContext = ServletActionContext.getServletContext();Map<String,HttpSession> sessionMap = new HashMap<String,HttpSession>();Object sessionMapObj = servletContext.getAttribute("LOGINED_USER_SESSION_MAP");if (sessionMapObj!=null){sessionMap = (Map<String,HttpSession>)sessionMapObj;}if (sessionMap.containsKey(loginId.toUpperCase())){//如果登过录就销毁以前登录的SessionHttpSession session = sessionMap.get(loginId.toUpperCase());if (session!=null && !ServletActionContext.getRequest().getSession().getId().equals(session.getId())){try {session.invalidate();} catch (Exception e) {LOG.info("session被重复销毁:["+e.getMessage()+"]");}}}sessionMap.put(loginId.toUpperCase(), ServletActionContext.getRequest().getSession());//将当前session重新放入MapservletContext.setAttribute("LOGINED_USER_SESSION_MAP", sessionMap);} /** * 登出 * @param loginId */public synchronized static final void logout(String loginId){if(loginId==null || "".equals(loginId))return;ServletContext servletContext = ServletActionContext.getServletContext();Object sessionMapObj = servletContext.getAttribute("LOGINED_USER_SESSION_MAP");if (sessionMapObj==null){return;}Map<String,HttpSession> sessionMap = (Map<String,HttpSession>)sessionMapObj;if (sessionMap.containsKey(loginId.toUpperCase())){//如果登过录就销毁以前登录的SessionHttpSession session = sessionMap.get(loginId.toUpperCase());if (session!=null){try {session.invalidate();LOG.info("根据登录ID:"+loginId+"找到Session,执行销毁");} catch (Exception e) {LOG.info("session被重复销毁:["+e.getMessage()+"]");}}sessionMap.remove(loginId.toUpperCase());}} public synchronized static final String getAdminName(){return AuthConfig.adminName; } /** * 获得管理员信息 * <p> * admin,0000 * </p> * @return */public synchronized static final String getAdminInfo(){return AuthConfig.adminName+","+AuthConfig.adminPwd;}}
登录调用示范:
/** * 诊所登录 * * @return */public String doLogin() {SystemLog log = new SystemLog();String zsid = super.getParam("zsid").toString();String zsmm = super.getParam("zsmm").toString();log.setLoginId(zsid);log.setKind("1");log.setIp(request.getRemoteHost());if (StringUtils.isBlank(zsid) || StringUtils.isBlank(zsmm)) {super.addValidateMsg(VALIDATE_MSG, "诊所编号密码不能为空");log.setContent("诊所登录失败:[诊所编号密码不能为空]");systemLogService.addLog(log);return "toLogin";}if (zsid.equals(AuthConfig.adminName)) {super.addValidateMsg(VALIDATE_MSG, "非法的诊所ID");log.setContent("诊所登录失败:[非法的诊所ID]");systemLogService.addLog(log);return "toLogin";}try {if (cliniqueService.authentication(zsid, zsmm)) {super.addAttr(IAction.LOGINED_USER, zsid, VScope.SESSION);UserUtil.setLoginedUser(zsid);// 保存线程局部变量AuthenUtil.multipleLoginDetect(zsid);log.setContent("诊所" + zsid + ">登录>成功!");systemLogService.addLog(log);return "login_success";}} catch (Exception e) {super.addValidateMsg(VALIDATE_MSG, e.getMessage());log.setContent("诊所登录异常:[" + e.getMessage() + "]");systemLogService.addLog(log);return "toLogin";}super.addAttr(IAction.LOGIN_MSG, "用户名密码不正确", VScope.REQ);log.setContent("诊所登录失败:[用户名密码不正确]");systemLogService.addLog(log);return "toLogin";}
登出调用示范:
public String logout() {if(!StringUtils.isBlank(getCurrentUser())){SystemLog log = new SystemLog();log.setLoginId(getCurrentUser());log.setKind("1");log.setIp(request.getRemoteHost());log.setContent("诊所" + getCurrentUser() + ">注销>成功!");AuthenUtil.logout(getCurrentUser());systemLogService.addLog(log);return "logout_success";}else{return "logout_success";}}
- 1楼macrotea3天前 16:16
- 这是业界的经典解决方案?请教一下一般是否是这样实现的?