Shiro介绍(五):WildcardPermission解读

对于Role-Permission两级权限体系,大多数情况下,我们都是直接使用Shiro提供的WildcardPermission来实现细粒度的权限控制。

Shiro为我们定义了一个抽象的权限描述字串:
【资源】:【操作】:【实例】

例如:”user:create,update”,”user:delete:100110”,等等。

Shiro的通配符权限,可以这样使用【以下描述中『授权』指分配给当前用户的权限,而『校验』指在注解或JSP标签中写的权限】:

  1. 授权(user),校验(user),结果(通过)
  2. 授权(user),校验(user:create),结果(通过)
  3. 授权(user:create),校验(user:update),结果(不通过)
  4. 授权(user:create),校验(user:create,update),结果(不通过)
  5. 授权(user:create,update),校验(user:update),结果(通过)
  6. 授权(user:create),校验(user:*),结果(不通过)
  7. 授权(user:*),校验(user:create),结果(通过)
  8. 。。。

那么,这个支持通配符Permission的内部逻辑又是如何实现的,是一个比较有意思的话题。
来看代码:

    public boolean implies(Permission p) {
        // 只支持与另一个WildcardPermission作比较
        if (!(p instanceof WildcardPermission)) {
            return false;
        }

        WildcardPermission wp = (WildcardPermission) p;

        List<Set<String>> otherParts = wp.getParts();

        int i = 0;
        for (Set<String> otherPart : otherParts) {
            // 如果当前permission长度比other permission短,校验通过
            // 参见示例(2)
            if (getParts().size() - 1 < i) {
                return true;
            } else {
                Set<String> part = getParts().get(i);
                //如果当前permission的当前Part不是*,
                //且又不能包住other permission的当前Part,则校验不通过
                //否则继续,直到处理完当前permission的所有节
                // 参见示例(3)(4)
                if (!part.contains(WILDCARD_TOKEN) && !part.containsAll(otherPart)) {
                    return false;
                }
                i++;
            }
        }

        // 上面逻辑没有返回false,开始检查当前permission多出来的part
        // 如果多出来的part只要有一个不为*,则不通过。
        // 参见示例(7)
        for (; i < getParts().size(); i++) {
            Set<String> part = getParts().get(i);
            if (!part.contains(WILDCARD_TOKEN)) {
                return false;
            }
        }

        return true;
    }

代码加了注释,从这个实现逻辑来看,尤其是那一句!part.containsAll(otherPart),我们就明白了缺省情况下,permission如果用逗号分隔多个时,是『与』的关系,而非『或』。

这时,我们来回忆一下在注解中,有这样的写法@RequiresPermissions(value={"channel:edit","channel:create"},logical=Logical.OR),说明Shiro还是在帮我们处理多个权限共存时,AND或OR的问题。所以,这里不能用@RequiresPermissions("channel:edit,create")

也就是说,我们常说的一个原则『分配权限时可以模糊,但校验时一定要明确』,参见示例7(正例),6(反例)。

猜你喜欢

转载自blog.csdn.net/sharetop/article/details/50250651
今日推荐