zoukankan      html  css  js  c++  java
  • 吐槽下若依(RuoYi)系统的权限系统(shiro和spring-security)

    起因

    有接触若依,目前是前后端分离版本是用的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呢?同样会对初学者参考时造成困扰。

    总结

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

  • 相关阅读:
    8.池化内存分配
    7.netty内存管理-ByteBuf
    6.ChannelPipeline
    5.接入客户端连接
    4.Netty执行IO事件和非IO任务
    3.NioEventLoop的启动和执行
    2.NioEventLoop的创建
    1.netty服务端的创建
    微信订阅号开发初探
    jmeter自动化脚本编写
  • 原文地址:https://www.cnblogs.com/vishun/p/13566528.html
Copyright © 2011-2022 走看看