吐槽下若依(RuoYi)系统的权限系统(shiro和spring-security)

时间:2024-02-29 12:45:04

起因

有接触若依,目前是前后端分离版本是用的spring-security,不分离版本是用的shiro,两个权限都有些想吐槽的地方

shiro

RuoYi为例,当前是4.4.0版本,我们直接看realm的配置,在com.ruoyi.framework.shiro.realmdoGetAuthorizationInfo方法中:

    /**
     * 登录认证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
    {
        UsernamePasswordToken upToken = (UsernamePasswordToken) token;
        String username = upToken.getUsername();
        String password = "";
        if (upToken.getPassword() != null)
        {
            password = new String(upToken.getPassword());
        }
        SysUser user = null;
        try
        {
            //这里
            user = loginService.login(username, password);
        }
        catch (CaptchaException e)
        {
            throw new AuthenticationException(e.getMessage(), e);
        }
        ...省略
        //就是这里
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
        return info;
    }

上方SimpleAuthenticationInfo的第二个参数直接将UsernamePasswordToken中的password传递过去了,但如果用shiro自身的逻辑的话,应该是将从数据库查询出来的user中的password传递过去,而且系统在ShiroConfig中压根没有配置HashedCredentialsMatcher凭证匹配器,所以shiro默认是用simpleCredentialsMatcher也就是密码会直接字符串比较不做任何md5等哈希加密来进行密码匹配,所以这里如果传递UsernamePasswordToken中的password那后续的assertCredentialsMatch(token, info)密码比较方法必然成功,也就是相当于把shiro自带的密码验证功能废掉了,但若依系统之所以还能正常运行,是因为它实现了自己的密码比较,就在上方的user = loginService.login(username, password)中。但真的有这个必要自己实现吗?个人感觉不是很好,因为很多初学者会参考这些系统来学习shiro的配置什么的,感觉会造成困扰。

spring-security

RuoYi-Vue为例,当前版本是3.1.0

  • 目前token采用的是jwt的方式,但令人费解的是,所有的token又在redis做了存储,以便于可以直接控制失效等,如果是redis中用黑名单的形式来剔除token的话还可以理解,但系统明显是所有的token都存储了,那这里用jwt的意义何在,还不如直接返回一个不重复的uuid作为token多好,不用每次都传递jwt的这么多数据,也不用额外解析jwt
  • 然后是系统中很多地方用LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest())来获取当前用户数据,这个需要再解析token,然后从redis缓存中读取的数据,不明白为什么不直接从SecurityUtils.getLoginUser()中获取,明明已经封装好方法了。
  • 然后是权限校验方面,我们先看UserDetail的实现类LoginUser
    /**
    * 登录用户身份权限
    * 
    * @author ruoyi
    */
    public class LoginUser implements UserDetails
    {
        private static final long serialVersionUID = 1L;
    
        ...省略
    
        /**
        * 权限列表(看这里)
        */
        private Set<String> permissions;
    
    ...省略
    
        public LoginUser(SysUser user, Set<String> permissions)
        {
            this.user = user;
            this.permissions = permissions;
        }
    
        ...省略
        //还有看这里
        @Override
        public Collection<? extends GrantedAuthority> getAuthorities()
        {
            return null;
        }
    }
    
    
    这里明明有getAuthorities这个方面来设置权限,但偏偏不用,而是自己定义一个permissions来存放权限,然后导致@PreAuthorize("@ss.hasPermi(\'system:dict:list\')")也只能能自定义了一个PermissionService来再实现hasPermi等方法,但这样有意义吗?为啥不直接用getAuthorities呢?同样会对初学者参考时造成困扰。

总结

以上就是吐槽点,若依系统本身还是不错的,而且每个作者都有自己的想法,希望越做越好吧。