异地(异浏览器)登录后登录挤掉先登录的账号 java应用

方法一:比较复杂,在项目比较小没引用消息中间件的情况下且没有redis
MyMapSessionId类(采用单例模式,对象有且只有一个,存在的时候不用创建,为空的时候创建对象) 用于用户登入时保存sessionId , 作为后期对同一帐号是否多地登入作工具(如果项目中引用了redis做缓存这个类可以省略)
public class MyMapSessionId {

   private static MyMapSessionId m;
   private HashMap<Long,String> mymap;

   private MyMapSessionId() {
      mymap = new HashMap<Long,String>();
   }

   public static synchronized MyMapSessionId getInstance() {
      if (m == null) {
         m = new MyMapSessionId();
      }
      return m;
   }

   public synchronized void AddSession(Long id, String sessionID) {
      mymap.put(id, sessionID);
   }

   public String getSessionId(Long id) {
      String SessionId = (String) mymap.get(id);
      return SessionId;

   }
   public synchronized void DeleteSessionId(Long id){
      mymap.remove(id);
   }

}
/**
  * 用户登录拦截器
  * @author :geng
  * @date :2017-12-19 9:37
  */
public class UserAccountInfoLoginInterceptor extends HandlerInterceptorAdapter {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String requestHeader = request.getHeader("X-Requested-With");
       //查询用户是否登录
        UserAccountInfo userAccountInfo = (UserAccountInfo) request.getSession().getAttribute(Session_Constant.USERACCOUNTINFO);
        if (userAccountInfo !=null){
            HttpSession session = request.getSession();
            String Id = session.getId();//获取当前会话sessionId
            Long id  = userAccountInfo.getId();
            MyMapSessionId m = MyMapSessionId.getInstance();
            String sessionId = m.getSessionId(id);//获取保存的sessionId
            if (sessionId!=null && sessionId.equals(Id)) {
                return true;
            } else {
                session.invalidate();
                String str="yideng";//已登录
                request.getRequestDispatcher("/portal/denglu?ab="+str).forward(request,response);
            }
            return true;
        }else {

         //检查是否是ajax请求
            if (StringUtil.isNotEmpty(requestHeader) && requestHeader.equalsIgnoreCase("XMLHttpRequest")){
                response.getWriter().print("logout");
            }else {
                response.sendRedirect(StringUtil.getBasePath(request)+"/portal/denglu");
            }
            return false;

       }

    }
}
/**
 * 跳转登录页面
 */
@GetMapping("/denglu")
public String todenglu() throws ServletException, IOException {
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setContentType("text/html; charset=utf-8");
    //查询用户是否登录
    UserAccountInfo userAccountInfo = (UserAccountInfo) session.getAttribute(Session_Constant.USERACCOUNTINFO);
    UserAccountSafeInfo userAccountSafeInfo = (UserAccountSafeInfo) request.getSession().getAttribute(Session_Constant.USERACCOUNTSAFEINFO);
    String str = request.getParameter("ab");
    if (userAccountInfo != null && userAccountSafeInfo != null) {
        return "portal/denglu";
    } else {
        if (str != null && !str.trim().isEmpty()) {
            // 判断是否是因为被挤下来而被跳转到登入页面
            request.setAttribute("Msg", "您的账号已经在另一处登录,请重新登录!");
        }
        return "portal/denglu";
       /* request.getRequestDispatcher("portal/denglu").forward(request,response);*/
    }
}

/** * 用户的登录jsp页面 */

<script>
    //处理账号同时登录时挤掉另一个账号
    var Msg= '${Msg}';
    if (aabb != null && aabb != "") {
        alert(Msg);//
    }

</script>
/**
 * 用户的登录controller
 */
@RequestMapping("/login")
@ResponseBody
public Map<String, Object> login(String mobile, Model model, String password) {

//简单的密码手机号校验逻辑省略

Map<String, Object> hashmap = new HashMap<>();

Long id = userinfo.getId();// 登录用户(如果后期需要加密需要对其进行加密处理)
HttpSession session = request.getSession();
String sessionId = session.getId();
MyMapSessionId.getInstance().AddSession(id, sessionId);// 将用户的id和当前会话sessionId绑定
//如果登录成功
hashmap.put("loginResult", "登录成功");
return hashmap;

}

方法二:在有redis和token情况下,就会变得简单很多

/**
 * 拦截器
 * 
 * @Description TODO
 * @author geng
 * @date: 2018年3月27日 下午2:17:05
 */
public class Interceptor extends HandlerInterceptorAdapter {
   private static final Logger logger = LoggerFactory.getLogger(AppInterceptor.class);

   @Override
   public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
         throws Exception {
      /**
       * 对来自后台的请求统一进行日志处理
       */
      // 签名处理过程 start....
      AppReturnBean returnBean = new AppReturnBean();
      String token = request.getHeader("Authorization");
      System.out.println("token =" + token);
      if (StringUtil.isEmpty(token)) {
         returnBean.setRespDesc("请求失败,token参数不存在");
         returnBean.setRespCode(App_Constant.FAIL);
         StringUtil.sendJsonData(response, JSON.toJSONString(returnBean));
         return false;
      }
      try {
         /* 校验token */
         JWToken.verifyToken(token);
         Long baseId = JWToken.getBaseId(request);
         String tokeninredis = JedisUtils.get(baseId + "baseId");
         if (!token.equals(tokeninredis)) {
            returnBean.setRespDesc("异地登录");
            returnBean.setRespCode(App_Constant.FAIL);
            StringUtil.sendJsonData(response, JSON.toJSONString(returnBean));
            return false;
         }
      } catch (Exception e) {
         e.printStackTrace();
         returnBean.setRespDesc("Token验证失败,请重新获取");
         returnBean.setRespCode(App_Constant.TOKEN_FAIL);
         StringUtil.sendJsonData(response, JSON.toJSONString(returnBean));
         return false;
      }
/**
 * 用户的登录controller
 */
@RequestMapping("/login")
@ResponseBody
public AppReturnBean login(String mobile, Model model, String password, String longitude, String latitude) {
String token = request.getHeader("Authorization");//得到token令牌
AppReturnBean appReturnBean = new AppReturnBean();
Map<String, Object> hashmap = new HashMap<>();

//省略校验和逻辑

String tokeninredis = JedisUtils.get(baseId + "baseId");
//处理异浏览器手机登录
if (!token.equals(tokeninredis)) {
    JedisUtils.set(baseId + "baseId", token);
}

}

猜你喜欢

转载自blog.csdn.net/orecle_littleboy/article/details/82463877