您的位置:首页 > 编程语言 > Java开发

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

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

首先,考虑不能重复登录的问题。在项目中,我使用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用户单点登录异常情况处理之用户的非正常退出》。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: