权限设计及算法(PHPE)

PHP 专栏收录该内容
45 篇文章 0 订阅

  

权限设计及算法

Posted by: trooman 2005-12-28 12:05
权限设计

大概有这几种模式:
用户+组+角色+权限
用户+组+权限
用户+角色+权限
用户+权限


最近看了别人的设计方法,大多以“整数”来表示权限值,如添加、浏览、删除和修改,分别用1、2、4、8这几个整数来代替,不过,各人的做法有所不同,举例如下:

1.用2的n次幂组成权限值的集合,如1、2、4、8、16...,某用户的权限值为其子集中的整数之和,如 7=1+2+4,5=1+4。如果要从数据库检索包含某几种权限的用户,则先把这几种权限值相加,假设和为k,然后select * from table where 1 and 用户权限值 = 'k';如果要判断某用户有哪些权限,则取出其权限值k,分别用k&1,K&2,K&4,k&16...,如果为真,则表示有值等于“&”右边整数的权限,例如,如果k&4为真,则此用户有权限表中值等于4的权限;

2.用质数2、3、5、7、11...组成权限集合,某用户的权限为其子集中各整数的乘积,如 210 = 2*3*5*7,我觉得这种方法很有趣,难点在于如何分解质因数;但我有些不认同原作者的提法,他认为权限之间可能存在包含关系,如某用户有删除权限,则其一定有浏览权限,要不然就没法删除,事实确实是这样,不过我认为这样太复杂了,容易出错,我觉得权限最好是“原子”的,互不干扰,也就是说某用户有删除权限而没浏览权限则其无法进行删除操作,因为他看不到东西,解决这个矛盾的关键是在给用户赋权时,把浏览权限也赋给他;

3.不用整数,而是用“向量表”方法(也许我说的不一定对),把所有可能的权限按一定的顺序排列,如添加、浏览、修改、删除...,用户的权限值为固定100位长度的字符串,如100010100001....01,从左起每一位对应一种操作权限,如果有这种权限,则此位的值为1,反之,则为0,作者之所以把用户权限值固定为100位,我想是考虑到升级问题,但我认为这还不够科学,我认为用户的权限值长度应小于权限个数,举例如下:
权限排列表:添加、浏览、修改、删除,用户A有添加和浏览的的权限,则其权限值为11,用户B有浏览和修改的权限则其权限值为011,用户C有浏览和删除的权限则其权限值为0101,这样设计的好处为:当权限表中增加别的权限时,不会影响用户表或角色表;

4.我曾经的做法,在后台管理中把权限分为两大类:栏目权限和操作权限,每个栏目对应一个目录,操作权限细分为浏览、添加、修改和删除,用户进入系统后首先判断有没有栏目权限,然后判断有没有操作权限,判断栏目权限相对简单一些,首先获取访问页面的路径path,然后分解出目录,对应用户拥有的目录权限,如果此目录包含在用户有权管理的目录数组中(从数据库取出),则其有进入此目录的权限,否则,没有,然而,在判断操作权限好象有些麻烦,但突然想到添加、浏览、修改和删除与我的文件命名规则是基本是对应的,但有点不同的是,我把添加和删除的功能合并在一个文件中了,例如文件名为proAddEdit.php,幸好意识到修改文件时多了个传递参数id,于是,我用正则解决了这个问题,今天看来,这种方法似乎过时了,因为不适应面向对象的思想和用框架体系来开发系统!

以上是个人粗浅的认识和描述,若有错误,请各位指正,希望高人给些意见!

Posted by: trooman 2005-12-28 16:02
咋个这么冷清,一个发表点意见的都没有?

Posted by: axgle 2005-12-28 16:05
已收藏。

Posted by: Donyad 2005-12-28 16:41
1 2 3 的思想是相同的,只是实现上的手法不同而已
而3后半部分楼主的例子,恕偶愚笨,看不懂

3的做法是很C的,driver级别或者系统级别的程序很常用
比如*nix下的文件权限0755 0777之类

方法1 跟 方法3 原型是一模一样的,就是二进制位,方法3 是对这个的一个字符串模拟
二进制 十进制
100 4
+ 1 1
------------
101 5

用相互独立的位来标志权限,就是为了原子性,素数同样具有这个特性
所以派生出2的做法,而分解质因数,我并不认为这个会是一个问题,因为三种方法都需要去检查所需要的权限
既然是检查,除一下所需要的质数即可

而3里面所说的要变长的问题
1和2正好在概念上回避了这个问题
实际上,在C里面用二进制,有个对齐的问题,就是要8位8位的申请,8位8位的用,无所谓太长了浪费
只是象方法3这样用字符串来模拟二进制时会有浪费
而方法1 2在真正保存时,也是保存成一个int,也是一个申请过来就那么多位的二进制空间,无所谓浪费

扩展和弹性上,方法1和方法2是没有影响的
对方法3来说是个问题,那是因为方法3模拟得不好... 方法3感觉有猪鼻子插葱之嫌

--------------

敲code多了,文字表达能力可能不行了,偶说不对的或说不清的地方欢迎大家拍砖,3q

Posted by: lihun21 2005-12-28 19:27
做个记号先
学习一下
现在还没有用到这么深的权限系统
我现在只有三种权限的用户,所以还没有考虑那么多
超级管理员->普通管理员->普通用户
我想,我用的是这种模式
用户+权限

Posted by: wwccss 2005-12-28 20:06
楼主的文章不错。Donyad兄分析的也很有水平。smile_tongue.gif

Posted by: cozo 2005-12-28 20:10
这种东西只要一种方法就可以了。
我就只使用第一种。

Posted by: bitQ 2005-12-28 21:47
这个方法我有看到过~~~


用二进制表示权限,不会互相影响,期待做个涉及到这个的项目

高手就是高手~~`

Posted by: BinzyWu 2005-12-28 22:01
具体怎么标记权限 这个较无所谓
一般的系统
RBAC是已经够用的.

一般Access Controller有3种
user based
group based
role based

RBAC有成熟的理论基础, 你可以搜索以下, 能搜到很多论文.

但如果不是一般的应用系统, 那么权限系统可能设计需要较为特别. 这里只有普遍理论, 未必有普遍方法.


Posted by: terpomo 2005-12-29 00:31
学习了

Posted by: bleakwind 2005-12-29 01:14
我比较落后,我是将每个人的权限组成的数组序列化放入数据库。。。
每次载入页面初始化出来。。。

Posted by: nameless 2005-12-29 08:51
见过一个用方法3做的权限判断,操作很方便,也很灵活

栏目权限用的直接把栏目标识用界定符分隔连接,操作时判断有没有这个标识,简单,对栏目数过多且操作员过多的时候这个数据库效率应该不高(如果操作员能超过 10W 的话),呵呵

Posted by: trooman 2005-12-29 11:18
QUOTE (nameless @ 2005-12-29 08:51)
见过一个用方法3做的权限判断,操作很方便,也很灵活

栏目权限用的直接把栏目标识用界定符分隔连接,操作时判断有没有这个标识,简单,对栏目数过多且操作员过多的时候这个数据库效率应该不高(如果操作员能超过 10W 的话),呵呵

是的,我也认为方法3不会比二进制的效率差,在具体使用时可以用like,str_replace等,还可以模拟二进制。

那种所谓的“栏目”权限管理,现在已经过时了,但思想还是可以沿用的,如“对应栏目”改成“对应模块”,但实现方式已经截然不同了!

Posted by: sean.zhuo 2005-12-29 13:51
哪位大哥能給我講解一下"角色"這個概念嗎?不懂什麽叫角色.

Posted by: KnightE 2005-12-29 14:50
1和3,本质还是一样的吧。
1有个好处,节省空间。LZ提到开100个权限用来升级。不过我遇到过一个超过100个权限类别的系统,而且用户树较多。所以后来压成了16进制存储(原来还是一样),就类似1的处理方法了。
不过3最大的好处应该在于直观(其实如果权限项很多的话,也不直观了,呵呵)。

个人认为“权限储存和判断的方法”其实还不是“权限设计”的重点和难点。我们还需要考虑其他东西。比如权限的设计结构(RBAC/GBAC/UBAC)的选择,比如权限在应用系统中的使用……

我GBAC(基于组的权限控制)用的比较多。一般的逻辑是:

  • 组成树型结构,用户跟组结点
  • 判断权限,从组根目录开始往用户所在组进行遍历。起始权限为“禁止”
  • 遍历时,子组权限覆盖起始权限,直至用户。
  • 最后用户权限覆盖起始权限。得到最终权限码。

虽然貌似有些繁杂,不过较灵活些。


其次谈谈权限的使用。通常的做法(至少我是这么做的),即在“所需”时,根据以上逻辑判断某用户相对某权限“是否通过”,例如(乱写的,只是想表示是在需要是进行判断):
CODE

// when someone posts a new topic
if ($access_controller->check($user, 'post'))
{
// access passed
$user->post($content);
}
else
{
// access denied
$sys->accessDenied();
}



而我一直很想尝试的,是这样一种权限使用方法:即在$user实例出来时,已经装配好他拥有的权限(check once, run anywhere),例如:
CODE

class User
{
var $sid;
var $name;
var $passwd;
var $email;
// ...

function __call()
{
// it must be a ACCESS DENIED process here
die('no permission');
}

// maybe no other methods here...
}

// we need overload the User class in PHP4
// for the __call magic method
overload('User');
$user = new User();

// we need a AccessInject method to inject accesses into user object
$access_controller->access_inject($user)
// then, the user object includes its access methods...

// ok, we use the user's method directly
$user->post($content);
// if the user object includes the post method, it has the right permission...



随便写了点,没有很仔细考虑结构和命名,希望能表达清楚我的意思。
抛砖引玉……

Posted by: LuciferStar 2005-12-29 17:40
做过一个表单,用法1和3保存多选的表单数据。

Posted by: james.liu 2006-01-05 17:10
如果是面向对象的,,倾向于小K的想法

用户登陆时,,如果用户名,密码,什么都对的,允许他登陆时,,实例化用户信息,包括权限

Posted by: gudai 2006-01-11 16:06
权限设计。头疼的问题。


来源:http://club.phpe.net/index.php?act=Print&client=printer&f=2&t=11828

  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

1.PHP4.23在WindowsXP下的IIS和Apache2两种服务器上的安装实例 http://www.phpe.net/articles/260.shtml 2.Apache服务器配置全攻略(一)http://www.phpe.net/articles/94.shtml 3.WinXp sp1+apache2.0+php5.0+mysql+ phpMyAdmin 安装全功略[教学]http://warmsun.51.net/article/show.php?id=207 1.两种Web服务器(IIS和Apache)可同时存在,只要保证他们的监听端口号不同即可,如:IIS用默认的80,而将Apache的配置为8080。 也可暂时让IIS停止服务,而让Apache用80。 2.在D:\apache2\Apache2\conf下的httpd.conf中,注释符号为#,但不能在一条未注释语句的后面添加注释内容,否则出错,如: httpd.conf中的第173行LoadModule php5_module modules/php5apache2.dll后就不可,否则提示"LoadModule takes two arguments,a module name and the name of a shared object file to load it from". 编写的php文件必须放在Apache2\htdocs文件夹下。 3.要修改的文件内容: (1)D:\program files\php-5.0.0RC3-Win32下的php.ini-dist 文件 改名为php.ini 搜索extension_dir = ./ 这行,并将其路径指到你的PHP5目录下的ext目录,比如:    extension_dir = "D:\program files\php-5.0.0RC3-Win32\ext" 第545行改为extension=php_mysql.dll (2)D:\apache2\Apache2\conf下的httpd.conf文件 第173行改为LoadModule php5_module modules/php5apache2.dll 前提是将php5apache2.dll(在D:\program files\php-5.0.0RC3-Win32下)复制到D:\apache2\Apache2\modules下。 第761行#AddType application/x-tar .tgz下添加如下内容: AddType application/x-httpd-php .php AddType image/x-icon .ico 找到: #NameVirtualHost * 修改为: NameVirtualHost 127.0.0.1 //或localhost 找到: <VirtualHost 127.0.0.1> 修改下面几行: ServerAdmin (你刚才安装时候输入的管理员信箱) DocumentRoot D:\apache2\Apache2\htdocs ServerName Apache2 # ErrorLog logs/dummy-host.example.com-error_log # CustomLog logs/dummy-host.example.com-access_log common </VirtualHost> 增加默认文件: 找到DirectoryIndex 这行,可以这样修改,添加默认的文件名: DirectoryIndex index.php default.php index.htm index.html default.htm default.html 最后,在该文件末尾加上下面两行 ScriptAlias /php/ "D:\program files\php-5.0.0RC3-Win32" Action application/x-httpd-php "/php/php.exe" 119行修改为Listen 8080,即端口号为8080,80已被IIS占用了。 213行修改为ServerName 127.0.0.1:8080 240行修改为<Directory "D:\program files\php-5.0.0RC3-Win32"> 255行修改为<Directory "D:/apache2/Apache2/htdocs"> 632行左右将# DefaultLanguage nl修改为DefaultLanguage GB2312,即默认语言是简体中文。 709行左右将AddDefaultCharset ISO-8859-1修改为AddDefaultCharset gb2312,即增加默认的字符集为简体中文。 若不修改上面两行,则显示的文字是乱码?修改后并不会立刻改过来,好象重启系统或计算机后才好。 (3)要复制的文件: PHP5的"php5ts.dll"复制到C:\WINDOWS\system32目录下. PHP5的PHP.ini(按上面所述修改)和LibMysql.dll必须都放在windows目录下,才支持mysql。 到此Apache的PHP环境已经完全建立了 测试:   用记事本新建个文件,写下下面几行,保存到D:\apache2\Apache2\htdocs目录下, 这个目录就是你的站点跟目录,命名为phpinfo.php.然后在浏览器中输入http://localhost/phpinfo.php就可以看到想尽的关于PHP的信息了。 <? phpinfo(); ?> 4. 如果万一不知道自己改的哪一个部分使Apache启动不起来了,你可以切换到Apache安装目录下的Conf文件夹, 将http.conf文件删除掉,再将Apache的默认配置文件httpd.default.conf改名成http.conf即可。如果你想进一步的了解Apache的配置, 可以参考一下本站的另一篇文章"Apache服务器配置全攻略"(http://www.phpe.net/?n=ReadArticle&a=94)。 5.遇到的问题解决办法: 4.将php5apache2.dll(在D:\program files\php-5.0.0RC3-Win32下)复制到D:\apache2\Apache2\modules下。 若直接写成LoadModule php5_module D:\program files\php-5.0.0RC3-Win32\php5apache2.dll,则也提示LoadModule takes two arguments,a module name and the name of a shared object file to load it from". 若直接写成LoadModule php5_module modules/php5apache2.dll,而事先未将php5apache2.dll(在D:\program files\php-5.0.0RC3-Win32下) 复制到D:\apache2\Apache2\modules下,则在点击 开始|所有程序|Apache HTTP Server 2.0.50|Configure Apache Server|Test Configuration 时提示"Cannot load D:/apache2/Apache2/modules/php5apache2.dll into server: \xd5\...",到D:/apache2/Apache2/modules/一看,发现 没有php5apache2.dll这样的文件,所以将其复制过去即可。 5.之后测试配置(Test Configuration)成功(成功后的显示是闪一下就消失了),但启动(Start)时,提示一个警告“PHP Startup: Unable to load dynamic library 'd:\program files\ php-5.0.0RC3-Win32\ext\msql.dll' -找不到指定的模块。”,但连续提示两次后Apache Server启动了,为了连警告都没有,我试着 将msql.dll(在D:\program files\php-5.0.0RC3-Win32下)复制到D:\program files\php-5.0.0RC3-Win32\ext下,但此时重新启动是提示警告 “PHP Startup: Invalid library (maybe not a PHP library) 'msql.dll'”。同样地,连续提示两次后Apache Server启动了,此时,运行 几个简单的程序没问题,但不知这个警告有什么后患,拭目以待吧。 原因是php.ini文件中的extension=msql.dll,将他改为extension=php_mysql.dll即可,但要将libmysql.dll复制到C:\WINDOWS下才可。 6.结果发现将libmysql.dll(在D:\program files\php-5.0.0RC3-Win32下)复制到C:\WINDOWS下,这个问题就迎人而解了。此时,再次启动 Apache Server时就没任何问题了,但有时会出现异常情况:发送错误报告之类的,但这种情况很少。 7.第一次装的是mysql5.0alpha,但显示的数据库只有test,而没有mysql,但显示mysql的表时却能全部显示,后来将mysql5.0alpha 删除改装mysql4.0,尽管在my.ini中修改了datadir和basedir(修改为mysql4.0的),但在WinMySQLAdmin1.4中的Variables选项卡中显示的内容仍是有关mysql5.0alpha 的内容,如:datadir和basedir。以上工作是在一小时内完成的,结果到第二天,WinMySQLAdmin1.4才开始重新启动,但速度很慢 (本身启动速度就很慢,好象得3-4个小时吧)。右键“红绿灯”图标,选择Win NT下的Install the Service,最后再Start the Service。 这时,绿灯亮,表示启动了。发现Variables选项卡中显示的内容正确了。但在Databases选项卡中显示的还只是test数据库,没有mysql. 在WinMySQLAdmin1.4没有启动前,点击mysql\bin下的mysql.exe时,只显示黑屏,或很快闪过出现 "ERROR 2003: Can''t connect to MySQL server on ''localhost'' (10061)“,。 而启动后,显示mysql>提示符。
©️2021 CSDN 皮肤主题: 书香水墨 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值