吐槽下若依(RuoYi)系统的权限系统(shiro和spring-security)
起因
有接触若依,目前是前后端分离版本是用的spring-security
,不分离版本是用的shiro
,两个权限都有些想吐槽的地方
shiro
以RuoYi为例,当前是4.4.0
版本,我们直接看realm
的配置,在com.ruoyi.framework.shiro.realm
中doGetAuthorizationInfo
方法中:
/**
* 登录认证
*/
@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
呢?同样会对初学者参考时造成困扰。
总结
以上就是吐槽点,若依系统本身还是不错的,而且每个作者都有自己的想法,希望越做越好吧。