shiro实现限制单用户多地登录

账号在同一时间只能在一处登录(非单点登录)实现方式大致三种:

  1. session隔离
  2. 数据库记录
  3. shiro实现

shiro实现方式
1.shiro配置




    

        
        
        
        
        
        
    


    
    
    
    
        
        
        
    

2.代码

  @Autowired  
  private SessionDAO sessionDAO; 

    /**
     * 实现用户登录
     * @param username
     * @param password
     * @return
     */
    @RequestMapping(value = "doLogin")
    public ModelAndView Login(String username, String password) {
        ModelAndView mav = new ModelAndView();
        User user = loginService.getUser(username);
        if (user == null) {
            mav.setViewName("login");
            mav.addObject("msg", "用户不存在");
            return mav;
        }
        if (!user.getPassword().equals(password)) {
            mav.setViewName("login");
            mav.addObject("msg", "账号密码错误");
            return mav;
        }

        Collection sessions = sessionDao.getActiveSessions();
        for (Session session : sessions) {
            System.out.println("登录用户" + session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY));
           
            //shiro session可以拿到已经登陆的username
            System.out.println("登录用户" + session.getAttribute("userName"));

        if (username.equals(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY))) {
                mav.setViewName("login");
                mav.addObject("msg", "该用户已登录");
                // session.setTimeout(0);  //这里就把session清除
                sessionDAO.delete(session); //session清除,  
                return mav;
            }
        }


        // 登录后存放进shiro token
        UsernamePasswordToken token = new UsernamePasswordToken(user.getName(), user.getPassword());
        Subject currentUser = SecurityUtils.getSubject();
        currentUser.login(token);
        //httpSession
        currentUser.getSession().setAttribute("loginName",username);
        //shiro Session
        currentUser.getSession(true).setAttribute("userName",username);

        // 登录成功后会跳转到successUrl配置的链接,不用管下面返回的链接。
        mav.setViewName("redirect:home");
        return mav;
    }

3.结束!


  • shiro获取所有在线用户方法
//apache shiro获取所有在线用户:
Collection sessions = sessionDAO.getActiveSessions();
for(Session session:sessions){
    System.out.println("登录ip:"+session.getHost());
    System.out.println("登录用户"+session.getAttribute(DefaultWebContext.PRINCIPALS_SESSION_KEY));
    System.out.println("最后操作日期:"+session.getLastAccessTime());
}

  • session移除另外一种方式
/*
 *在 LocalAuthorizingRealm 中,用户登录进行认证之前,先将该用户的其他session移除
 */
@Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String userName = (String)authenticationToken.getPrincipal();
 
        //处理session
        DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
        DefaultWebSessionManager sessionManager = (DefaultWebSessionManager)securityManager.getSessionManager();
        Collection sessions = sessionManager.getSessionDAO().getActiveSessions();//获取当前已登录的用户session列表
        for(Session session:sessions){
            //清除该用户以前登录时保存的session
            if(userName.equals(String.valueOf(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY)))) {
                sessionManager.getSessionDAO().delete(session);
            }
        }
 
        String pwd = null;
        return new SimpleAuthenticationInfo(userName,pwd,getName());
    }

你可能感兴趣的:(shiro实现限制单用户多地登录)