一个权限管理的方案,大家来讨论一下优缺点

eastliangliang 2002-11-21 06:11:17
小弟刚刚接触实际应用,不知应用程序中的权限管理该如何做,今天下午偶然想到了一个方案,请各位高手点评一下优缺点,顺便提供几个权限管理的成功方法。谢谢。



建立一个权限表,包括权限等级,函数标志。用户在登录时用自己的用户名和密码登录之后,在用户表里记录自己的权限等级,以后每次调用函数都检查用户的权限等级和这个函数的关系。例:
用户表
用户名 密码 权限等级
Liu 123 1
Zhang 234 2

权限和相应函数对照表
权限等级 函数标志
1 Aaa
2 bbb
1 bbb

用户每次调用函数提供自己的用户名(session)函数可能如下:
procedure Aaa(const session, pwd, out isSuccess)
var
procedureID:String;
begin
isSuccess := false;
procedureID := ‘Aaa’;//函数标志,不是函数名,也可以和函数重名。

Select * from权限和相应函数对照表,用户表 where用户名=session and 密码 = pwd and 用户表.权限等级=权限和相应函数对照表. 权限等级 and函数标志=procedureID;

If 记录数=0 then exit;//如果此用户名所拥有的权限不拥有此函数的使用权
//则退出。
……//否则执行函数。
……
isSuccess := true;
end;

修改权限等级可执行的函数时,只需在表中插入或删除记录即可

为了不让用户了解更多的组件内部函数,可以自己编写一个程序来进行权限表的修改。

优点:权限管理清晰方便。可以在代码级设定权限。
缺点:每个函数调用都要查询数据库,不知是否服务器受得了。


一个改进方法:


组件模块建立一个全局数组,存放每一个函数调用者的权限等级,在初始化时从数据库中提取并赋值。用户提交自己的权限等级,然后在函数中判断

用户每次调用函数提供自己的权限等级(level)函数可能如下:
procedure Aaa(const level, out isSuccess)
begin
isSuccess := false;
if level <> gloabLevel.getlevel(Aaa);//gloabRight.getRight()为一个类成员方
//法,用于返回函数标志为Aaa的权限等级。
Exit
Else
……//执行函数
……
isSuccess := true;
end;
end;

优点:只在模块初始化时读一次数据库,减少了系统额外负担。
缺点:当一个函数标志对应多个权限等级时,需要编码做额外处理,暂时没仔细想怎么做。无法对用户提供的level做判断,只能假定是合法的,和直接提供session而不提供密码是一样的。


另一种改进方法:

权限表
权限等级 权限执行码(暂定)
1 111
2 110
3 100

其中权限执行码根据函数表和权限和相应函数对照表生成
函数表
函数名 二进制编码
Aaa 001
Bbb 010
Ccc 100

权限和相应函数对照表
权限等级 函数标志
1 Aaa
1 Bbb
1 Ccc
2 Bbb
2 Ccc
3 Ccc

用户登录后,从数据库中找出他所拥有权限的执行码发给用户,每次用户调用的时候传递一个执行码,在函数中进行判断

用户每次调用函数提供自己的权限执行码(exeCode)函数可能如下:
procedure Aaa(const exeCode, out isSuccess)
begin
isSuccess := false;
if (exeCode 逻辑与 001) = 0 then exit
else
……//执行函数
……
isSuccess := true;
end;

优点:用户提供的是一组看上去无意义的二进制数,提高的攻击的难度。
缺点:函数中权限执行码是写死的,而且随着函数的增多,权限执行码会很长。


两种改进方法的结合:
组件模块初始化时从数据库中动态调出每一个函数的二进制编码,然后在函数中用gloabRight.getRight()来取得保存在类中的二进制编码进行比较。这样可以在外部定时修改函数的二进制编码,从而调整权限对应的权限执行码,这样当泄漏权限执行码时可以避免长期的损失。而且避免了第一种改进方法中“当一个函数标志对应多个权限等级”时的麻烦。




注:关于gloabRight.getRight()

gloabRight为模块内部的一个类,定义如下:

先定义一个结构体,用于放置函数标志和相应的执行码。

type RRright = record
functionID:String;
functionCord:Tstream;//由于执行码可能很长,因此Delphi中用流来存储,具
//体编程语言自己决定类型
end;
type TgloabRight = class
private
Right: array of Rright;//动态数组,用于存放函数标志和相应执行码数组大
//小由函数表的记录数决定。
function getRight(const functionID:String;):TStream//按函数标志取得相应
//的执行码
public
constructor Create;//构造函数,从数据库中读取信息并初始化Right数组。
destructor Destroy;//析构函数,用于释放Right数组。
End;


用流来存取函数执行码是否可行?在数据库中怎么存储?


感谢您的耐心阅读!
代码仅供描述,有的地方不规范,见谅。

欢迎提供成功的权限管理的案例!
...全文
426 38 打赏 收藏 转发到动态 举报
写回复
用AI写文章
38 条回复
切换为时间正序
请发表友善的回复…
发表回复
jf1234 2003-03-11
  • 打赏
  • 举报
回复
s
qsfsea 2003-02-24
  • 打赏
  • 举报
回复
gz
eastliangliang 2002-11-26
  • 打赏
  • 举报
回复
哪个是致命错误,哪个是漏洞,两位指出来啊。大家一起讨论一个可行的方案啊。
bluemeteor 2002-11-26
  • 打赏
  • 举报
回复
一句话:功能越多,漏洞越多
lance09 2002-11-26
  • 打赏
  • 举报
回复
有个致命的错误................


学习中........
CDSoftwareWj 2002-11-26
  • 打赏
  • 举报
回复
















你要好好看看Windows 2000 Server 中对用户的管理就可以了 hehe^^


用户----角色-----组

feiniao921 2002-11-26
  • 打赏
  • 举报
回复
我没细看你的方案,因为觉得太复杂了,我不知道你是纯技术性的探讨,还是要在工程中实施.如果是算法问题,我们可以有时间细细探讨.如果要在工程中实施,我给你的意见是---首先看是成本,第二看是需求,第三看是维护.

当然怎么复杂的东西也得看你精力如何了,别做完验证后就没劲在做别的了,呵呵!
lxpbuaa 2002-11-25
  • 打赏
  • 举报
回复
older(疲倦的程序员) 所说“一个字节可以管理8个功能”其实很不错的。
我现在控制权限用两个表:
用户:
UserID PassWord Note
权限:
UserID ModalID RightStr
我是作一个MIS系统,共8个模块(ModalID)。权限分为读写、读、写、增加、修改、删除、不能访问等等,分别用自然数1……9等(必要时可以扩展到多位)表示。RightStr就是存放这些数(当然其顺序涉及到其他复杂一点的控制)。另位同时实现相同功能用了6个表,权限管理模块写得非常复杂、运行效率低,而且权限管理员使用非常不方便。
eastliangliang(青苹果)(十年铸剑,汗祭青锋) :“三层结构要客户端越瘦越好”并不是绝对的概念,必须考虑兼顾其他方面;三层概念的提出也是为了提高开发和运行效率阿。其实“客户端构建一个简单的ProcID表”(其实那Delphi来说,就是一个TStrings足以;它是用户登录时服务端一次性传过来的,并不需要真的建立一个数据表)可以减少网络流量,因为过程调用的权限判断不需要提交到服务器,这样可以跳高系统运行效率和稳定性。这种方法对于大规模用户和网络带宽不很大、网络传输和你的服务环境不是非常稳定的情况,相信非常有用。

—————————————————————————————————
宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。
—————————————————————————————————
eastliangliang 2002-11-25
  • 打赏
  • 举报
回复
谢谢楼上的众兄弟。
lxpbuaa(桂枝香在故国晚秋)兄所说的在客户端构建一个简单的ProcID表,用户在调用服务器函数时要进行判断,就需要在客户端编程时就考虑哪个函数对应哪个ProcID。总觉得这样客户端受束缚较大,三层结构要客户端越瘦越好,客户端建立复杂的权限判断,似乎不利于系统维护。
二进制权限码似乎不是一个很好的解决方法。
哪位兄弟对role based access control有研究,来谈一下大概思想。
older 2002-11-24
  • 打赏
  • 举报
回复
权限管理应该加入组别的概念,否则权限控制起来比较麻烦
个人权限同组别权限是一个或的关系
我现在喜欢用位来管理具体操作的权限,一个字节可以管理8个功能,加密就看你的了
cnsuyong 2002-11-24
  • 打赏
  • 举报
回复
权限相互独立是好主意,如果划分等级则很糟糕;
预先定义角色和允许管理角色是好主意,这样可以很方便地实现授权管理;
直接授权用类似“01”串的编码是好主意,建议作为利用角色授权的附加手段。
skyclin 2002-11-24
  • 打赏
  • 举报
回复
而我的意见是
先这样一个表
用户编号 用户名 密码 权限级别 权限码
01 林 123 1 01010111111010101

这个权限码是根据窗体有多个按钮或控件性的事件
当产生一个新的用户时,必须控制哪个按钮能不能用这一个级别来

再根据管理员给新用户配置的使用权限,来产生权限码
一个“0”或一个“1”代码某个按钮能不能使用
lxpbuaa 2002-11-23
  • 打赏
  • 举报
回复
权限管理方案的设计,应该根据具体应用而定。好的权限管理方案,应该兼顾权限管理程序办法的简便和管理程序使用的方便,层次少、结构简单、条例清晰,最终要的:易于扩展。
传统的
“建一个权限表,内容为各个操作
建一个部门表
建一个角色表
建一个用户表,关联部门表角色表
建一个角色权限对照表
如此可以用部门+角色交叉管理

虽然可以实现任何权限管理案例,但是太麻烦了,效率很低。
对于你的这个情况,我觉得你说的:
用户表
用户名 密码 权限等级
Liu 123 1
Zhang 234 2

权限和相应函数对照表
权限等级 函数标志
1 Aaa
2 bbb
1 bbb
就足够了。至于Aaa(下面简称ProcID)等可以是函数标示、接口标示、对象标示等。
接下来,我想就是在怎么实现权限检查。就2种吧:
1、用户登录时将她能使用的ProcIDs(如果有对应的使用等级,比如读、写等,可用1、2等标示)发给他,在客户端构建一个简单的ProcID表。
2、用户调用时才检查权限。
可能1在实际实现上方便一些。另:绝对没有必要存储函数实际Code到数据库,那样费事而且没有什么价值。

—————————————————————————————————
宠辱不惊,看庭前花开花落,去留无意;毁誉由人,望天上云卷云舒,聚散任风。
—————————————————————————————————
cbyhnchen 2002-11-23
  • 打赏
  • 举报
回复
關注
xh_hero 2002-11-22
  • 打赏
  • 举报
回复
收藏下来!慢慢学习!谢谢!
hongqi162 2002-11-22
  • 打赏
  • 举报
回复
我觉得建立一个超级用户足够了!

超级用户可以将低级用户变成高级用户!


这只是我个人的一点看法!!!!
eastliangliang 2002-11-22
  • 打赏
  • 举报
回复
感谢各位兄弟的关注!

用数据库的权限管理确实很方便,可是没有数据库的时候呢?(现在没有数据库的程序好像不多啦。呵呵)。

我也想直接把权限管理推给数据库,甚至推给COM+也行。可是领导要我把权限管理到函数级,只好想解决办法啦。
总的思想是方便客户的管理,总不能要求客户到数据库内去修改权限吧。
对数据库的权限管理了解不多,求教一个成功的解决方案。

用流的方法确实不好,当函数无限增多时有大问题。暂时没想出更好的方法。

区域权限,部门权限,好多东东啊,原来如此复杂。是够我头疼的。
继续讨论吧。
yelanne 2002-11-22
  • 打赏
  • 举报
回复
收藏下来!慢慢学习!谢谢!
伯猿虫 2002-11-22
  • 打赏
  • 举报
回复
用户名 密码 权限 部门
Liu 123 ABC AA
Zhang 234 BEF BB

1、我觉得这样的表就够用了,其中权限字段中的每个字母代表用户可以授予的权限。

2、再把所有的菜单项invisible掉,根据不同的用户的权限,显示不同的菜单项,还可通过类似部门这种字段来进行辅助控制。

3、如果还需要更进一步的控制可以在程序中可以建立一个数组来存储但前用户权限,在程序中加以判断!!

4、我觉得这样实现起来比较容易,而且只要一次查询,就可以实现!而且这样的权限便于加密。不易被破解!
CloneCenter 2002-11-22
  • 打赏
  • 举报
回复
理想的方案是将你系统的用户和数据库系统的用户关联起来,定义好数据库用户的权限,也就定义好你的程序中用户的权限了,而且不需要你写那么多的代码。系统执行过程中,如果进行操作,权限不足,是不会成功的。但是这样需要设计好数据库用户的具体权限,也是比较复杂的。

或者你可以自己写一个 class ,所有需要用户检查权限的窗体都可以从这个 class 来继承,在这个 class 中定义好一个权限的标志,可以让每个子类来实现这个标志,在这个 class 创建或者是窗体 Create 的时候来检查权限。这样比你那样写的代码要少的多。

你的使用流的方法不是很好,但是好象想法比较的大胆,但是实现起来应该是比较困难的,因为涉及的内容来深奥了一些,而且没有必要深入到编译器代码这一层,而且放到数据库中,你怎么把它 load 到内存中,并且 run 呢?有许多的问题。
加载更多回复(18)

5,388

社区成员

发帖
与我相关
我的任务
社区描述
Delphi 开发及应用
社区管理员
  • VCL组件开发及应用社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧