shiro账号安全(每一个账号只能同时存在于一台设备上)

今天我们记录一下shiro的一个账号安全。

在网上看了一下其他人的实现,个别案例显得繁琐,配置太过于沉重,今天在这里介绍一种简单的方法。

1.首先说一下我实现的思路

  • 首先,在这之前我们知道,当用户登陆成功之后,shiro会将用户的一些信息存储的sessionDao,同时,对于同一个浏览器对不同的账号,登陆时产生相同的sessionId,这也导致了用户信息之间的覆盖,不同的浏览器对于不同的账号,会产生不同的sessionId,(网上有一些根据sessionId来实现的我是没有看懂)
  • 既然我们知道shiro会将用户存储到sessionDao 那么,我们就可以从shiro中拿出这些登陆的信息,然后作比较,根据id或者name随意啦,如果匹配上了,那么我们就将这个session强制下线,添加我们新的session,那么我们的功能就实现了。

 2.xml配置(我只提供最简单的配置,如果没有特殊的要求是够用了)

        根据上面的思路,我们总结一下,我们需要用到的有sessionDao,sessionManage(session的管理器当然需要拉),就OK了,当                然shiro框架的整合配置就不说了,肯定要配置啊。

  • 1.加载我们的sessionDao
  • 2.加载我们的sessionManage,她需要依赖我们的sessionDao


        
    
  •  3.在sessionmanag
  • e加载到securityManage中,

    
        
        
        
        
    

到这了xml的配置就ok了

 

3.修改我们的认证方法


    @Autowired
    private SessionDAO sessionDAO;

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken aToken) throws AuthenticationException {
        UsernamePasswordToken token = (UsernamePasswordToken)aToken;
        String username = token.getUsername();
        //判断用户名是否存在
        User user = userService.selectUser(username);
        //声明一个user用来获取sessionDao中的user
        User userSession = null;

        if(user != null){
            //获取在线的session
            Collection sessionCollection = sessionDAO.getActiveSessions();
            for (Session session : sessionCollection){
                //session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY); 获取simpleAuthenticationInfo的第一个参数的值
                if(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY) != null) {
                    //根据session build出一个subject
                    Subject subject = new Subject.Builder().session(session).buildSubject();
                    //拿到这个登陆的对象
                    userSession = (User) subject.getPrincipal();
                    //判断她的code和我现在登陆的code是否一致  (code是我在数据库里面设置一个标识码  采用uuid  保证唯一性 这里你可以id)
                    if (user.getCode().equals(userSession.getCode())) {
                        //两者一致的时候,设置这个session的失效时间 (0:立刻)
                        session.setTimeout(0);
                        break;
                    }
                }
            }
            AuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
            return authenticationInfo;
        } else{
            throw new AuthenticationException("用户名错误!");
        }
    }

是不是和我们最初写的认证方法没什么区别,就多了一个foreach中的循环,注入了一个sessionDao,(就是我们在springbean.xml声明的那个sessionDao,)

到现在,你的账号就只能同时存在一台设备上了。喜欢就评论一下吧!

你可能感兴趣的:(shiro)