Spring+shiro报 there is no session with id【已解决】

``查阅网上的各种办法都没解决 就研究了一下代码

 @Override
    public boolean onAccessDenied(ServletRequest request, ServletResponse response)throws Exception {
        Subject subject = getSubject(request,response);
        // 没有登录授权 且没有记住我
        if(!subject.isAuthenticated() && !subject.isRemembered()){
            // 如果没有登录,直接进行之后的流程,如果是登录则 终止后续的 
            return true;
        }
        // 获得用户请求的URI
        HttpServletRequest req=(HttpServletRequest) request;
        String path = req.getRequestURI();
       logger.info("===当前请求的uri:" + path);
       Session session = subject.getSession();
***if(path.equals("/login/login")||path.equals("/stamp/selectCount")||path.equals("/contract/selectCount")||path.equals("/WarningInfo/selectCount")||path.equals("/message/getList")){
	     return true;
	 }***
       logger.info("session时间设置:" + String.valueOf(session.getTimeout()));
        try{
            // 当前用户
        	UserInfo user = (UserInfo) subject.getPrincipal();
            String username = user.getLoginName();
            logger.info("===当前用户username:" + username);
            Serializable sessionId = session.getId();
            logger.info("===当前用户sessionId:" + sessionId);
            // 读取缓存用户 没有就存入
            Deque<Serializable> deque = cache.get(username);
            logger.info("===当前deque:" + deque);
            if (deque == null) {
                // 初始化队列
        
                deque = new ArrayDeque<Serializable>();
            	logger.info("deque初始化:" + deque);
            }
            // 如果队列里没有此sessionId,且用户没有被踢出;放入队列
            if (!deque.contains(sessionId) && (Boolean)session.getAttribute("kickout") == false) {
                // 将sessionId存入队列
                deque.push(sessionId);
                // 将用户的sessionId队列缓存
                cache.put(username, deque);
              	logger.info("deque push:" + deque);
            }
            // 如果队列里的sessionId数超出最大会话数,开始踢人
            while (deque.size() > maxSession) {
                logger.info("===deque队列长度:" + deque.size());
                Serializable kickoutSessionId = null;
                // 是否踢出后来登录的,默认是false;即后者登录的用户踢出前者登录的用户;
                if (kickoutAfter) { // 如果踢出后者
                	System.out.println("踢出后者");
                    kickoutSessionId = deque.removeFirst();
                } else { // 否则踢出前者
                  	System.out.println("踢出前者");
                    kickoutSessionId = deque.removeLast();           
                }
                // 踢出后再更新下缓存队列
                cache.put(username, deque);
                try{
                    // 获取被踢出的sessionId的session对象
                    Session kickoutSession = sessionManager
                            .getSession(new DefaultSessionKey(kickoutSessionId));
                    if (kickoutSession != null) {
                    	kickoutSession.setAttribute("kickout", true);
                    }
                }catch (Exception e){

                }
            }

            // 如果被踢出了,(前者或后者)直接退出,重定向到踢出后的地址
            if (deque.size()>0 && (Boolean) session.getAttribute("kickout") != null
                    && (Boolean) session.getAttribute("kickout") == true){
                // 会话被踢出了
                try {
                    // 退出登录
                 	System.out.println("被踢了!!"+subject.getSession().getId());
                    subject.logout();
                } catch (Exception e) { // ignore
                }
                saveRequest(request);
                logger.info("===踢出后用户重定向的路径kickoutUrl:" + kickoutUrl);
                return isAjaxResponse(request,response);
            }
            return true;
        }catch (Exception e){
            logger.error("控制用户在线数量【KickoutSessionFilter.onAccessDenied】异常!", e);
            return false;
        }
    }

因为新用户登录该系统,会同时调多个接口,每个接口都执行一次onAccessDenied 这样并发执行会导致多踢了用户的现象。所以我加入了筛选判断,把登录后首页调用的接口数目保持为1即可。
if(path.equals(“/login/login”)||path.equals(“/stamp/selectCount”)||path.equals(“/contract/selectCount”)||path.equals(“/WarningInfo/selectCount”)||path.equals(“/message/getList”)){
return true;
}

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值