Shiro之自定义权限标签的坑

项目中使用shiro做登录校验和权限管理,在配置权限时遇到小坑,记录一下。

环境:springboot+freemarker+shiro

场景:后台管理,配置菜单以及按钮权限,分为三个层级,一二级暂时只考虑是否查看权限,第三层级为页面按钮权限,分增删改查。详情看图:
Shiro之自定义权限标签的坑_第1张图片

问题:一二层级正常,第三层级权限不起作用!

权限标签定义如下:

标签定义 页面一 页面二
第一层级 one:view two:view
第二层级 one:page1:view two:page2:view
第三层级 one:page1:view:add two:page2:view:add

开始怀疑是数据库没有录入,查看后权限标签与角色已对应,排除。

后面怀疑是页面问题,后面把第三层级标签与第一二层级同一页面,依然不起作用,排除。

后面怀疑是权限标签定义问题,把第三层级标签改为one:page1:data:add,奇迹出现,权限生效。证实权限标签定义出了问题。

问题原因:权限标签定义问题

查看源码,一路debug后最终在org.apache.shiro.authz.permission中看到了关键所在,核心代码如下

// 当这个方法返回true时说明有此权限 
// 这个p是代表当前循环匹配到的权限标签 
public boolean implies(Permission p) { 
    // By default only supports comparisons with other WildcardPermissions 
    if (!(p instanceof WildcardPermission)) { 
        return false; 
    }

    WildcardPermission wp = (WildcardPermission) p;
    // 把当前标签转分割成一个set集合(如one:page1:view:add 会分割成[[one], [page1], [view], [add]])
    List> otherParts = wp.getParts();

    int i = 0;
    // 循环匹配权限标签
    for (Set otherPart : otherParts) {
        // If this permission has less parts than the other permission, everything after the number of parts contained
        // in this permission is automatically implied, so return true
        // 当全部循环匹配完没有返回false,则返回true,这个getparts()方法是获取当前角色当前循环的权限标签([[one], [page1], [view]]if (getParts().size() - 1 < i) {
            return true;
        } else {
            Set part = getParts().get(i);
            /*如果包含有‘*’而且不包含当前分割后的标签则返回false,
             *当用户可以查看页面,也就是说当前角色拥有one:page1:view标签
             *这里【!part.contains(WILDCARD_TOKEN)】返回true,第二个【part.containsAll(otherPart)】one会跟当前标签匹**配one,
             *也就是说这里全部循环完返回的都是false,所以最后都没true,于是在上面返回了一个true。
            */
            if (!part.contains(WILDCARD_TOKEN) && !part.containsAll(otherPart)) {
                return false;
            }
            i++;
        }
    }

总结:通过分析,我们看到了shiro在定义权限标签时,要注意匹配问题,不要存在包含问题,类似aaa和aaab,会导致后面标签失效。

你可能感兴趣的:(【框架】Shiro)