您的位置:首页 > 编程语言 > Java开发

shiro权限比对的一些坑

2018-04-04 14:21 197 查看
  最近在做shiro权限控制的时候,搭建完了环境给同事使用,同事使用的时候发现了一个bug,让我看看,bug是这样的,
       在freemarke中使用shiro标签,<@shiro.hasPermission name="sys:user:1111"></@shiro.hasPermission>发现标签不起作用,而这个权限在数据库是没有配置,查询出来的授权管理的权限列表里面也没有此权限,如果改为<@shiro.hasPermission name="sys:user:1113222"></@shiro.hasPermission>也是一样的,
据此我排查了以下几个问题:
1、shiro标签是引用进去的,可以使用,只是比对权限出现了问题,
2、换了其他权限控制是正常的。
最后没办法、只能跟踪源码去查看比对情况了。下面这个方法是最后比对权限的那个方法,编译后的源码,
这个方法在org.apache.shiro.authz.permission.WildcardPermission这个类中,实现了org.apache.shiro.authz.Permission接口,
//传进来的参数是要比对的权限、比如上面的sys:user:1111这个权限,

public boolean implies(Permission p) {
  //判断这个权限是否是WildcardPermission,否则否,这个没什么问题,
    if(!(p instanceof WildcardPermission)) {
      return false;
    } else {
      WildcardPermission wp = (WildcardPermission)p;
      List<Set<String>> otherParts = wp.getParts();
      int i = 0;
     //这个地方开始迭代传进来的权限 比如sys:user:1111会变成[[sys],[user],[1111]]
      for(Iterator i$ = otherParts.iterator(); i$.hasNext(); ++i) {
        //此时的权限控制失效的问题就出在这个地方 从0开始比对,比如比对到1111的时候,此时i=2  但是系统配的权限配的是          //sys:user,此时的this.getParts().size=2   再-1就等于1 <2 ,返回了true,此时才反应过来shiro的权限比对规则。
        Set<String> otherPart = (Set)i$.next();
        if(this.getParts().size() - 1 < i) {
          return true;
        }

        //判断系统配的权限是否包含通配符*,并且是否包含要判断的权限
        Set<String> part = (Set)this.getParts().get(i);
        if(!part.contains("*") && !part.containsAll(otherPart)) {
          return false;
        }
      }

        //如果要比对的两个权限,系统配置的,还有自己传进去要比对的两者,因为都转化为了list<set>结构,
//如果系统的当前权限list.size()小于了迭代次数i,并且不包含通配符*的时候就返回 false;
      while(i < this.getParts().size()) {
        Set<String> part = (Set)this.getParts().get(i);
        if(!part.contains("*")) {
          return false;
        }
        ++i;
      }
      return true;
    }
  }

此时bug出现的原因就是:同事配置了一个sys:user权限,但是他判断sys:user:1111的权限的时候,就返回了true,默认sys:user权限里面包含了sys:user:1111, 跟sys:user:*里面包含sys:user:1111一样的道理。
总结下shiro权限配置规则以及权限比对规则:shiro里面使用:作为权限分隔符,根据:作为正则来分隔并且转化为list<set>,
一般用如下配置:一级模块名(如用户、系统、菜单):二级子模块:操作标识符,  依次往下类推
如果要比对的两者权限中,一级模块名相同就比对二级,二级相同就比对三级, 如果包含有通配符*则有以下规则;
比如:sys:user:*(或者sys:user)中就包含了 sys:user:create,update,delete三个操作用户的权限
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  shiro java bug 随笔