【自然框架】之通用权限(六):权限到节点
2009-06-10 09:47 金色海洋(jyk) 阅读(7522) 评论(80) 编辑 收藏 举报
“直率没有错,但是也要考虑对方的承受能力呀!对方都承受不了了,你还直率,那就是你的错了!”
——我的名言,呵呵。
====================我就是传说中的,可爱的、无奈的、笑笑而过的分割线====================
继续,这是第六章了。我发现,越来越难了。终于把表结构都介绍完了,来到了如何应用的阶段了。有回复说我是跳过了设计阶段,恩,设计阶段基本上是在我的脑子里。当然这是一个不好的习惯。不弄出来个UML、ER这样的东东,别人怎么理解呢?又怎么能够严谨呢?不过不管怎么说,我还是要把我的想法、数据库表、实现方法、代码、Demo都拿出来,希望没有污染大家的眼睛。
不管我的东东好与不好,至少我是拿出来了,虽然还没有写完,但是没有严重的意外的话,我会坚持下去的。
通用权限想要写的文章目录:(这是第六章)
1、 简介、数据库的总体结构
2、 介绍人员表组
3、 介绍组织结构表组
4、 介绍角色表组
5、 介绍“项目自我描述表组”
6、 权限到节点
7、 权限到按钮
8、 权限到列表(表单、查询)
9、 权限的验证
10、 资源方面的权限
11、 角色管理的程序(给客户用的)
12、 权限下放
13、 个性化设置
A、 【自然框架】之通用权限(外传):杂谈
功能节点
【图一:功能节点的效果】
【图二:功能节点的数据】
先说一下功能节点,先看图一,左面的就是我所说的功能节点,这个节点是根据Manage_Function表里的数据显示的,就是说每一个节点都放在了表里面,显示的时候、提取数据然后绑定就可以了。
如果您查看WebUrl字段(图二),您会发现只有一个节点是Excel.aspx,其余的节点都是DataList.aspx。您是不是会想,这个是不是我写错了?或者是节点的功能还没有实现,先用了一个DataList.aspx来代替?这个没有写错,也不是临时占位用的。在自然架构里面,增删改查这一类的列表页面,95%以上都可以使用DataList.aspx页面。
在功能节点上面,单击一个节点以后,会根据节点里的WebUrl字段信息打开网页,然后会在网页后面加上一个参数?fid=xxx。这个fid就是FunctionID。就是说通过单击节点的方式进入的页面都会得到一个FunctionID的参数。这个参数是很有用处的,可以做很多的事情,比如做权限验证。稍后会有说明。
这里有一个特殊的字段sort,这个可能比较少见,也可能是一个不严谨的设计。这个字段的功能就是 —— 排序,对所有的节点进行排序。按照这个字段排序的结果,就是页面里面要达到显示顺序,这样就避免的在显示的时候的使用“递归”的方式。不知道有没有其他的非递归的方式,总之我是采用了这种方法。
权限到节点
说起来简单,正常提取数据的SQL语句是这样的。
DataTable dt = dal.ExecuteFillDataTable(sql);
Rpt.DataSource = dt; //绑定到Repeater
Rpt.DataBind();
那么加上权限呢?
角色表Role_Role里面的FunctionIDs 字段里面存放的就是角色可以访问的功能节点的ID的集合。比如我们建立一个“字典信息管理角色”,那么这个角色里面的FunctionIDs就是这样的“8,9,10,11,12,13,14,15,16”。
然后我们可以把FunctionIDs的值取出来,然后写成FunctionID in () 的形式就可以了。
代码如下。
string FunctionIDs = JYK.Common.UserManage.UserInfo.FunctionIDs; //获取登录人可以访问的节点ID。
string sql = "SELECT FunctionID, NoteTitle, NoteLevel, ParentIDPath, WebURL, Target FROM Manage_Function where FunctionID in (" + FunctionIDs + ") and IsShowNote = 1 ORDER BY Sort";
DataTable dt = dal.ExecuteFillDataTable(sql);
Rpt.DataSource = dt;
Rpt.DataBind();
列表页面验证
只是做到功能节点的显示与否这还不够,因为用户可以通过,直接在浏览器的地址栏里面输入网址的形式访问列表页面。所以呢,还需要在列表页面里进行验证。
列表页面里的验证分为两步,第一步验证传递进来的FunctionID是否是希望得到的。第二步是验证用户是否有权限访问这个FunctionID。
第一步好做,写一个if就可以了,第二步也简单,使用IndexOf就可以了。
对于DataList.aspx页面来说,任何一个FunctionID都是可以传递进来的,他可以根据这个FunctionID的不同而显示不同的页面。也就是说对于DataList.aspx只需要进行第二步的验证就可以了。
何谓通用?
1、功能节点的显示:只看Manage_Function里的记录,不用考虑业务需求,不用考虑项目里有哪些具体的功能节点。只要能够把业务需求变成功能节点的形式,写到Manage_Function表里面,那么就可以这种方式来显示成功能节点的形式。增加一个节点,减少一个节点,都不需要修改代码。增加一个节点,也就是在表里面添加一条记录,添加后会得到一个FunctionID,这个FunctionID就是这个节点的权限标志。
2、权限到节点:只需要加一个查询条件 FunctionID in () 就可以了,他只认FunctionID,不用考虑项目里面到底有哪些功能,有哪些节点。而角色表里面只需要记录可以访问的FunctionID就可以了。增加一个节点,减少一个节点,也不需要修改角色方面的代码,只需要调整一下Role_Role表里的记录。当然了,也不需要打开企业管理器来调整,我们可以写一个维护角色的功能(页面),用这个页面,客户自己都可以管理角色。
3、列表页面的验证:这个也是很简单的,抽象出来两个函数,然后在页面里调用一下就可以了。对于DataList.aspx页面来说就更简单了。
我想这就是通用吧。我把功能节点的现实与否变成了查询条件,我把权限的验证变成了检查数据库里有无匹配的记录。因为我是面向数据库的,所以我就这么做了。
还记得《我写项目的思路和“自然架构”》里面的那张图吗?
数据库作为间隔,把业务逻辑和实现代码给分离开来。现在从角色方面来看,确实做到了这一点。角色只对数据库(特定表里的数据)说话,不用考虑具体的业务需求。而数据库里的记录是根据具体的业务需求而添加的,添加了就可以了,不用去管具体的代码实现。
一个人拥有多个角色怎么办?
我的角色分为了两种,一种我叫做“正向角色”,就是规定可以访问哪些。另一种我叫做“拒绝角色”,就是规定不可以访问哪些。那么这些角色遇到一起会是什么样子呢?
1、多个正向角色,他们是“或”的关系,就是说只要有一个角色规定了可以访问,那么就是可以访问的。
2、正向角色与拒绝角色相遇,那么拒绝角色就是“一票否决制”,只要是它规定的不可以访问的节点,那么拥有在多的正向角色都是不能访问这个节点的。
3、拒绝角色的验证。先到拒绝角色的FunctionIDs里面找,如果传递进来的FunctionID在这个集合里面,那么就不能访问了。如果不在这个集合里面,那么再到正向角色的FunctionIDs里面找,如果在这个几个里面,那么就可以访问。
4、为什么要用“拒绝角色”
举个例子吧,就拿上面的“字典信息管理角色”来说,一般情况下,这个角色要包含字典信息里的所有的节点。但是有一天遇到一个特殊情况,某人可以访问字典信息里的节点,但是却不可以访问“表类型”这个节点。那么怎么办呢?
我们可以再定义一个角色,这个角色包含除“表类型”外的所有的字典信息里的节点。这是一种办法,另一种就是“拒绝角色”。
我们可以添加一个拒绝角色,这个拒绝角色就叫做“字典信息管理角色表类型除外”(一时想不出来好名字),这个拒绝角色“继承”(或者叫做关联)“字典信息管理角色”,通过“继承”的方式获得了“字典信息管理角色”的全部功能,然后在这个基础上,加上一个“拒绝”,就是说明要拒绝“表类型”节点的访问。
这么做操作起来可以方便一些,可以达到继承的一些效果。比如,字典信息里面又增加了一个节点“角色类型”,那么上面说的两种情况都可以访问,那就只需要修改“字典信息管理角色”就可以了。
这么做我想思路会更清晰一些。客户也应该更容易理解一些。
ps:写了五章了,从大家的回复来看,我心里是很没底的,我不知道大家看懂了没有,有没有什么问题,还是说我写的这些根本就不值得来提问题。或者是比较忙没时间细看。总之,我只能瞎猜,不知道大家的想法到底是什么。
所以呢,现在也到了具体的应用的阶段了,希望大家踊跃回复哦,只要回复不包含人身攻击,那就都没有问题。你说我的程序烂,不严谨,都可以,当然希望能够详细说明。帮我挑毛病,我是要感谢大家的。我对大家的疑问也会一一回复的。
您的回复,就是我前进的动力!谢谢大家!