事情的起因是帮班级开发了一个管理平台,其中的权限校验部分使用了shiro。上线后有一个同学发现了一个漏洞,可以造成任意用户登录,绕过Api的身份验证。

我们在使用shiro进行身份认证时,需要根据自己的需求实现Realm,实现doGetAuthentication(用户身份认证信息)以及doGetAuthorizationInfo(用于权限校验信息)。

问题代码

重写的doGetAuthenticationInfo方法,在使用userMapper查询到用户信息之后,将user存到了shiro的session之后。

@Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException,NumberFormatException {
        if (token.getPrincipal()==null){
            throw new UnknownAccountException();
        }
        Integer studentId = Integer.valueOf((String) token.getPrincipal());
        //取出数据库中的指定User
        User user= Optional.ofNullable(userMapper.selectByStudentId(studentId)).orElseThrow(UnknownAccountException::new);
        SimpleAuthenticationInfo info=new SimpleAuthenticationInfo(user,user.getPassword(),getName());
        Session session= SecurityUtils.getSubject().getSession();
        //存到shiro的session中(对于Web来说本质是HttpSession)
        session.setAttribute("USER_SESSION",user);
        return info;
    }

登录处:

Subject subject=SecurityUtils.getSubject();
        UsernamePasswordToken token=new UsernamePasswordToken(studentId,password);
        try {
            subject.login(token);
        }

之后的API处的身份验证:

if(!SecurityUtils.getSubject().isAuthenticated()) {
            return resultJson.error(401,"未授权");
        }
User user = CommonUtil.getUserFromShiroSession();
//其中的getUserFromShiroSession():
public static User getUserFromShiroSession(){
        return (User)SecurityUtils.getSubject().getSession().getAttribute("USER_SESSION");
    }

身份认证的逻辑就是:

点击收藏 | 5 关注 | 3
登录 后跟帖