基于角色的权限设计方案(PHP)
很多系统都会考虑用户的权限,比如,作为业务人员进入系统不能操作财务模块。一般小型系统,可能是直接对用户施加具体的权限项目。这种基于用户的权限分配系统,缺陷很多。第一、每增加一个新用户,都要对他的权限进行分配,比较繁琐。第二,具有相同权限的人,如果想调整权限(比如减少一个权限),需要对每个人进行权限调整,这也很繁琐,而且容易出错,比如漏掉某个人。如果系统的用户很多,这项调整工作将是苦差事。因此,基于角色的权限设计方案应运而生。
基于角色的权限系统是定义系统的各种角色,而用户属于某个角色。权限的变动只体现在角色上面,当角色的权限变动时,隶属于该角色的所有用户权限都随着改变。对于庞大的系统,基于角色的权限设计是首选。比如,某个跨国企业有10000个业务员,业务员属于该企业ERP系统里的一个角色。现在系统增加一个投诉模块的权限给业务员使用。这时,只需要修改业务员这个角色的权限,让他多一个投诉模块的权限,这样10000个业务员瞬间就具有这种权限了。
比如一个企业级的购物网站,采用下面的角色权限设计:
一个大系统可能细分为数十种甚至上百种具体的权限。现在我们采用二进制位来代表权限的有无。一个字节有8个位,如果用十六进制的字符来表示,就是2个字符可以代表8中权限,如0f其二进制位是00001111,他表示具有前四种权限。系统设计里,我们可以把每个权限对应到某个二进制位,这样就可以用少量的字符信息代表多种权限。
比如字符000300可以表示具有24中权限里的第9位和第10位权限。
注意,图中二进制从左到右是从低位到高位这样表示。按2个字符(即1个字节)代表权限,可以使各个字节之间没有必然联系。这样,字符越多,就可以表示越多的权限,而我们要做的只是把这些字符叠加在一起。把他们体现在数据库里,就是一个简单的字符串。可以想象,如果200个字符(即100个字节),可以表示800个权限,这几乎满足任何一个系统的权限设计了。
下面是笔者在日常的教学过程中,常常教给学生的权限设计代码片段(以PHP为例子)。
<?php
require'./session.php';
function IsHaveRight($AllRights, $Value)
{
//首先得到Value由哪个字节决定
$iCharPos = ($Value % 8 == 0) ? ($Value / 8): ($Value / 8 + 1);
$iBitPos = ($Value % 8 == 0) ? 7 : ($Value %8) - 1;
$CurAC = substr($AllRights, ($iCharPos - 1) *2, 2);
$CurAC = hexdec($CurAC);
//判断相应位置上的二进制位
if (($CurAC >> $iBitPos) & 1)
returntrue;
return false;
}
?>
<!DOCTYPE html PUBLIC "-//W3C//DTDXHTML 1.0 Transitional//EN""http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<htmlxmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type"content="text/html; charset=utf-8" />
<title>后台管理_增加或编辑角色</title>
<link href="../css/Back.css"rel="stylesheet" type="text/css" />
</head>
<scripttype="text/javascript">
function ChangeAC_Status(id)
{
varobjRoleList = document.getElementById('RoleList');
varCurRoleList = objRoleList.value;
varidV = parseInt(id);
variCharPos = (idV % 8 == 0) ? (parseInt(idV / 8)) : (parseInt(idV / 8) + 1);
variBitPos = (idV % 8 == 0) ? 7 : (idV % 8) - 1;
varCurAC = CurRoleList.substr((iCharPos - 1)*2, 2);
CurAC= parseInt(CurAC, 16);
varobjThis = document.getElementById('AC_' + id);
if(objThis.checked)
CurAC|= (1 << iBitPos);//将当前权限加进去
else
CurAC&= ~(1 << iBitPos);
varstrHex = CurAC.toString(16);
if(strHex.length == 1)
strHex= '0' + strHex;
CurRoleList= CurRoleList.substr(0, (iCharPos - 1)*2) + strHex
+ CurRoleList.substr((iCharPos - 1)*2 + 2,CurRoleList.length)
objRoleList.value= CurRoleList;
}
</script>
<body>
<?php