session登录控制 后一个踢掉前一个

最近实现项目中的用户重复登录控制,即新用户登录使前一个登录的用户强制下线 ,思路是这样的,在前台主页面写一个程序定时向后台发送请求获取后台信息来判断session是否失效,若失效强制下线。
(SSM框架为例)


一 Controller层
1. 定义两个全局MAP 来存放用户的登录帐号(userId),session和sessionId

//userid,session
public static Map<String,HttpSession>  MAP1 = new HashMap<String,HttpSession>();
//sessionId,userId
public static Map<String,String>  MAP2= new HashMap<String,Sting>();

2 定义一个静态方法 存储用户session,检查是否登录 (记得在用户成功登录后调用此静态方法

public static void userLogin(HttpServletRequset request){
String userId = request.getParameter("userId");
//当前用户
HttpSession session1 = request.getSession();
//当前用户session
String sessionId = request.getSession().getId();
//当前用户sessionId
MAP2.put(sessionId,userId);
//放入当前用户的sessionId 和 userId
HttpSession session = MAP1.remove(userId);//MAP1移除上个用户的session  若session为空 MAP1放入
      if(session != null){
             MAP2.remove(session.getId());  //session 不为空 根据sessionId 找到上个userId对应的session 移除
             session.setAttribute("msg","您的帐号已在另一处登录"); //session移除后向前台发送信息
                         }
       MAP1.put(userId,session1);

}

3.写一个方法向前台传值

@RequsetMapping(value="/check.do")
@RequseBody
public String checkLogin(HttpServletRequest request){
HttpSession session = request.getSession();
        if(session.getAttribute("msg") != null ){
                return  ResponseUtil.getMsg(session.getAttribute("msg") ); 
              //返回前台的信息,这里调用了一个封装好的返回工具类,可以单独使用io流返回值
                     }

}

二 前台(EXTJS为例)
1 前台主页面刷新不断向后台请求获取msg ,原理跟ajax轮循无异 , 在主页面中调用 checkLogin 方法

     checkUser : function(){
            Ext.Ajax.request({
                     method:"POST",
                     url:'Login/check.do'  //向后台发送请求
                     success : function(response){
                        var  responsJson = Ext.decode(response.responseText);  
                        var success = responsJson.success;
                        if(success) {
                           Ext.Mag.confirm({
                           title : '提示',
                           msg : responsJson.msg,   //从后台获取到的msg
                           buttons : Ext.Msg.YES,
                           fn : function(btn, text){
                                     if(btn == 'yes'){
                                      ---前台的注销方法--  //调用一个注销方法
                                                      };        
                                                   }
                                            }) 
                                    }
                                              }
                        )}
                        }
     checkLogin : function(){
     check = setInterval(checkUser , 3000);  //定时调用 checkUser方法
           }

PS:这种方法有个弊端,因为项目中的注销方法是直接销毁session,所以在同一浏览器同一用户登录注销后再次登录时会报错,session已经销毁,MAP中还存在session,报错。
解决方法:在销毁session时判断一下,在销毁方法中加以下代码

if(session.getAttribute("msg")!null){
session.invalidate();
//正常销毁
}else{
MAP.remove(MAP2.remove(session.getId()));
//销毁之前先根据sessionId找到MAP2中的userId,再移除MAP1中的session;
session.invalidate();
}

解决!

猜你喜欢

转载自blog.csdn.net/qq519423035/article/details/79142826