入门客AI创业平台(我带你入门,你带我飞行)
博文笔记

java web 用户单点登录的方案的基本实现

创建时间:2015-12-16 投稿人: 浏览次数:12492

      在实验室刚刚结束的项目中,有这样一个需求,一个账号同时只能在一个地方登录,如果在其他地方登录则提示已在别处登录,直到已登录账号失效或退出,同时,同一浏览器同时只能登录一个用户。

      首先,考虑不能重复登录的问题。在项目中,我使用session来存储用户的信息,用户登录时,创建一个session,将用户名,用户逻辑Id,登录时间等属性存放到该session中。考虑使用Application来实现禁止重复登录。定义一个Map<Long,String>类型的变量loginUserMap。其每条记录存储登录用户的逻辑Id和对应session的sessionId。这样,每次用户登录的时候遍历loginUserMap,如果没有对应的userlogicId或sessionId则允许登录,否则提示已在别处登录。

					// 判断是否重复登录
					isloginexists = false;
					ifsessioninvalidate = false;
					loginUserMap = (Map<Long, String>) acx.getApplication().get(WebConstant.LOGIN_USER_MAP);
					if (loginUserMap == null) {
						loginUserMap = new HashMap<Long, String>();
					}
					HttpServletRequest request = ServletActionContext.getRequest();
					String sessionId = request.getSession(false).getId();
					System.out.println("sessionId" + sessionId);
					for (Long userlogicId2 : loginUserMap.keySet()) {
						if (!userlogicId2.equals(userlogicId) && !loginUserMap.containsValue(sessionId)) { // 不同浏览器不允许相同用户重复登录
							continue;
						}
						
						if(userlogicId2.equals(userlogicId)&&!loginUserMap.containsValue(sessionId)){
							setIfsessioninvalidate(true);
						}
						isloginexists = true;
						break;
					}
					if (isloginexists) {
						setTip("loginexists");
						if(ifsessioninvalidate==true){
							request.getSession(false).invalidate();
					}
			
					} else {
					
						loginUserMap.put(userlogicId, sessionId);
						acx.getApplication().put(WebConstant.LOGIN_USER_MAP,loginUserMap);
						acx.getSession().put(WebConstant.USER_ID, getUsername());
						acx.getSession().put(WebConstant.USER_LOGICID,userManageService.findbyUsername(getUsername()).getLogicId());
						acx.getSession().put(WebConstant.LOGIN_TIME, new Date());
					       }


在用户退出的操作中,将loginUserMap中对应的用户logicId和sessionId清除,同时清除session中的用户信息。

		   Map<Long, String> loginUserMap = (Map<Long, String>)acx.getApplication().get(WebConstant.LOGIN_USER_MAP);
		   String username=userManageService.findByLogicId(userlogicId).getUserName();
		   if(loginUserMap.containsKey(userlogicId)){
			   loginUserMap.remove(userlogicId);	
		   }
		   session.getServletContext().setAttribute("loginUserMap", loginUserMap);
	    
		   Long id=(Long) session.getAttribute(WebConstant.USER_LOGICID);
		   if(id!=null)
			this.userManageService.userLogout(id);
		   
		   session.removeAttribute(WebConstant.USER_ID);
		   session.removeAttribute(WebConstant.USER_LOGICID);
		   session.removeAttribute(WebConstant.LOGIN_TIME);
		
		   //使Session失效
		   session.invalidate();
		
		   response.setHeader("Cache-Control","no-cache");
		   response.setHeader("Cache-Control","no-store");
		   response.setDateHeader("Expires", 0);
		   
    在session失效的监听器处理中,也做相同的操作,保证登录session超时时从loginUserMap中删除该用户,以保证后继账号能够正常登录。
   
public class SessionListener implements HttpSessionListener{
	 
	@Override
	public void sessionCreated(HttpSessionEvent event) {
		 
	}

	
	@Override
	public void sessionDestroyed(HttpSessionEvent event) {
		//监听session的失效和销毁
		HttpSession session=event.getSession();
		ServletContext application=session.getServletContext();
	
		try{
			 String username=(String) session.getAttribute(WebConstant.USER_ID);
			 Long userlogicId=(Long)session.getAttribute(WebConstant.USER_LOGICID);
			 Map<Long, String> loginUserMap = (Map<Long, String>)application.getAttribute(WebConstant.LOGIN_USER_MAP); 
			 if(loginUserMap.containsKey(userlogicId))
				 loginUserMap.remove(userlogicId);
			 application.setAttribute(WebConstant.LOGIN_USER_MAP, loginUserMap);
			  System.out.println("session:"+session.getId()+"已失效");
		 }
		 catch(Exception e){
			 	System.out.println(e.getMessage());
		 }
	}


}
     到这里,基本能做到限制用户的重复登录了,但是靠这些异常情况依然无法处理,如用户使用过程中关闭浏览器,再次登录时,由于信息记录在服务器端的application中且未按照正常安全退出流程执行,则执行登录操作会提示"已在别处登录"。要解决这个问题,参考博文《java web用户单点登录异常情况处理之用户的非正常退出》。

声明:该文观点仅代表作者本人,入门客AI创业平台信息发布平台仅提供信息存储空间服务,如有疑问请联系rumenke@qq.com。