学到了学到了
事情的起因是帮班级开发了一个管理平台,其中的权限校验部分使用了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");
}
身份认证的逻辑就是: