zoukankan      html  css  js  c++  java
  • 实现数据权限控制的一种方法

    在企业管理系统中,常常有这样的要求:
    1. 用户一般只能查看自己部门的数据
    2. 可以设置用户可以查看哪些部门的数据
    这种权限的控制,一般称为数据权限,与之对应的功能权限,则是系统中哪些功能可以使用——①菜单、按钮等元素能正常显示;②如果用户访问了本身不可见的功能,系统也能阻止(访问控制)。

    开发时间长了,就发现编程一般就是两个问题:
    1. 在哪里设置(数据从哪里来)
    2. 在哪里使用(数据到哪里去)
    比如工作流引擎,设置,即在界面上拖画流程图,并保存为特定的xml数据;使用,即流程引擎解读xml数据,使其正确的按照用户的意图执行程序。
    数据权限的问题,同样可以分成这两个问题来处理。

    设置的问题:
    在用户设置界面,设置用户的管辖权限

    image

    做到这样的设置界面,并不困难。

    在这里,主要要解决的一个问题是,如何把这种关系存储下来
    常规方案:使用关联表[用户ID,组织ID]
    可是发现,一旦组织机构数量多了以后(如省市县乡,一般一个省就有1000个乡/街道以上),再加上用户数量多了以后——往往是组织机构节点越多,则用户也越多。理论上,这个关联表的数据量将到达千万级(仅理论上,因为对于绝大多数用户来说,仅能访问本部门数据)。

    创新方案:组织机构使用code做主键,并且在用户表中新建字段为“已授权的组织(authorized_orgs)”,直接使用字符串逗号分隔的方式将该关系存起来。
    可是马上会发现,这个字段会很长很长,一个4级的组织,一般需要8位长的代码,如果选中的全部数据,按1000个单位来算,就会有9000长度(含逗号)的字符串。
    这里有一个取巧的办法,对于全选了数据,只保存上级单位的code,下级单位就不保存了——因为选中了上级就必然下级全部选上了。

    该办法要求上下级代码存在一种明显的关系,如上级代码为 0100,下级代码0101。
    这个取巧的办法,理论上依然不能规避很长的组织机构代码(如选的全部是叶子节点数据),但在实践中,却是很好的办法——应该很少出现全部只选叶子节点,而不选父级节点的。
    使用zTree(js的树)的代码,可以这样写

    if(zTree==null){ 
             return; 
         } 
         var nodes = zTree.getNodes(); 
         var arr = []; 
         for(var i=0; i<nodes.length; i++){ 
             pushToArray(arr, nodes[i]); 
         } 
         console.log(arr.join(",")); 
         obj.authorizedOrgs = arr.join(","); 
    
    function pushToArray(arr, node){ 
        if(!node.checked){ 
            return; 
        } 
        if(node.check_Child_State==2||node.check_Child_State==-1){//是节点完全选上(即不是半选状态)或叶子节点,直接添加 
            arr.push(node.code); 
        }else if(node.check_Child_State==1){//节点半选状态,递归往下找完全选中状态的 
            for(var i=0; i<node.children.length; i++){ 
                pushToArray(arr, node.children[i]); 
            }    
        } 
    }

    -----分割线:以上解决怎么设置的问题,以下讨论怎么解决使用的问题--------

    数据权限控制的基本思路,一般是会执行的SQL语句中添加where条件,以便限定查出的数据,
    如 where 所属机构 in (用户可访问的机构)
    而不是在数据查询出来之后,再到代码中进行过滤——因为一般都会对数据进行高效分页,如果已经查询出来数据,再在代码中进行过滤的话,就可能出现一页数据不足一页的情况,数据总数也会与实际页面上查出的数据行不一致。

    第一步,在需要进行过滤的表中,要添加一个字段,如org_code,标明每条记录所属的组织机构。
    第二步,在查询语句中加入过滤条件。
    我们要加入的SQL语句,大概如下:
    where 所属机构 in ('ZZ0101', 'ZZ0102',...)
    假如我们前面存的代码是'ZZ0100,ZZ0201',其中存的是其父级节点'ZZ0100',代表了 'ZZ0101', 'ZZ0102', ...
    所以要写成
    where ((所属机构 like 'ZZ01%') or (所属机构='ZZ0201'))
    拼凑这样的SQL语句估计也是比较麻烦的一件事,有没有简便一点的方法呢?答案是有。
    经查,oracle,sqlserver,mysql都是支持正则式查询的。
    这样,我们可以把'ZZ0100,ZZ0201'变成一个正则式,放入条件中进行查询即可!
    变成正则式就是 '(^ZZ01.*)|(^ZZ0201)',在mysql使用正则式查询,就是 where 所属机构 RLIKE '(^ZZ01.*)|(^ZZ0201)'
    变成正则式之后,也便于放入session中进行存储。
    什么,你的数据库支持正则式,orm不支持正则式,那还用orm做什么?

  • 相关阅读:
    保研练习题(5)
    保研练习题(4)
    保研练习题(3)
    保研练习题(2)
    保研练习题(1)
    基于邻接矩阵的拓扑排序--升级版
    基于邻接矩阵的拓扑排序
    vue 父组件调用子组件的函数
    vue 子组件调用父组件的函数
    JS 打乱数组顺序
  • 原文地址:https://www.cnblogs.com/binblog/p/3890031.html
Copyright © 2011-2022 走看看