1. 程式人生 > 實用技巧 >吐槽下若依(RuoYi)系統的許可權系統(shiro和spring-security)

吐槽下若依(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呢?同樣會對初學者參考時造成困擾。

總結

以上就是吐槽點,若依系統本身還是不錯的,而且每個作者都有自己的想法,希望越做越好吧。