大家好, 我目前做了一个通用权限系统
也想跟大家讨论下
我的通用权限系统设计是更换权限时候尽量不要涉及到代码修改<?php
/*
*控制访问表
* acl值 功能
* 1 需要登录
* 2 自身修改
* 4 需要组的权限集合
* 8 需要身份访问集合
* 16 身份被禁止访问
* 32 可访问的日期
* 64 可访问的周日
* 128 可访问的时间
* 256 输入密码才能访问
* 512 超级管理使用
*/
class aclACL extends acl {
public $routername="acl";
public $aclid='2'; //权限资源ID,如果登录人员没有拥用这个权限那么其(下面)它值都为0也不能访问
public $roledisable=array(9); //禁用身份
public $pwd=123456; //密码访问 ACL->noPwd();
public $date=array('begin'=>0,'end'=>0); //允许日期之间
public $hours=array('begin'=>0,'end'=>0); //一日内小时区间
public $weeks=array('begin'=>0,'end'=>0); //一周内周一到周七
public $aclgroup=array("create"=>"4,45,8"); //create需要的组才能创建
public $aclrole=array("all"=>"6","create"=>"7,95,78"); //create需要的角色才能创建,该组需要ID为6的角色才能访问
public $acl=array("all"=>0,
"index"=>4, //表列4表示检查组的组合
"delete"=>1, //删除只登录后删除,当然呆以设置为2或4
"update"=>1, //更新提交只能登录后才能更新,在这里做也防止非法、post,edit是不能访问显示编辑内容页
"createForm"=>1, //也不能新提交数据库
"edit"=>0, //登录才显示编辑框
"show"=>0, //不用登录也能显示
"create"=>1); //创新表单需要登录操作 可以设置某个组才能创建 } ?> 这个是要认证的文件模块是acl
每当用户访问acl模块时候,如果开启了认证那么会调用这个类
然后这个类会根据$acl 的all或index等值去做认证检查。
把这个文件放在router/acl目录里面就可以了,框架会自动认证如果用户没有相应的正向授权是无法访问相应的限制的。
比如crud create方法 负向权限为17 那按照前面解释应该是 需要登录和组授权 就是$aclgroup 数组中create的4 45 8三个组,
首先会员没有登录将提示登录,如果会员不在这三个组是无法访问该方法的会提示没有权限。目前router可以自己根据情况开启用acl控制
方法是在xxxxRouter.class.php文件中 添加 public function isAcl(){}
可以返回权限文件名比如返回curd,那么自动会调用curdACL.class.php类和名
curdRouter类设置验证
<?php
class curdRouter extends controller{
//返回 RBAC 控制访问列表验证类默认是跟router同名也就是curd
//可以不写这个函数,那么不会启用通用权限系统。
public function isAcl(){}
public function index()
{
$booktype=M("booktype");
$this->pager=C("pager");//取得分类
$this->pager->setPager($booktype->count(),10,'page');//取得数据总数中,设置每页为10
$this->assign("list",$booktype->orderby("bookid desc")->limit($this->pager->offset(),10)->fetch()->getRecord());
}
public function login(){ //登录页面
}
public function logout(){ //退出页面 MY()->logout(); //退出登录
redirect(url_for("guestbook/index"),"退出成功",3);
}
public function noAcl($mask) { //处理一下如果没有权限转向登录
redirect(url_for("guestbook/login"),"需要登录",3);
}
public function loginpost() { //登录提交地方 简单处理下登录认证
if($_POST['author']=='queryphp'&&md5($_POST['pwd'])==md5('123456'))
{
MY()->setLogin(); //设置登录状态
redirect(url_for("guestbook/adminlist"),"登录成功",3);
}
redirect(url_for("guestbook/login"),"登录失败",3);
}
<?php
/*
*登录信息基本类
*权限表可以缓存数据,登录时候恢复。
*/
class mybase {
public $options=array();
public $uid;
public $username;
public $isadmin;
public $role=array(); //我使用的身份
public $group=array(); //我所在组
public $grouprole=array(); //组的身份
public $mygroupMar=array(); //我拥有管理的组
public $mygroupOwn=array(); //属于我的组
public $acl=array(); //主动控制表 groupacl和myacl控制权限集合 内容是rbac的rbacid
public $groupacl=array(); //组拥用的控制权限
public $myacl=array(); //我的身份拥用的控制权限
public $loginfaild=0; //登录失败次数 如果超过这个数应该禁止IP登录几分种
这是基本
可以把myUser.class.php放在项目lib目录里面
<?php
class myUser extends mybase {
}
?>
使用MY()函数就可以取得myUser了。
也想跟大家讨论下
我的通用权限系统设计是更换权限时候尽量不要涉及到代码修改<?php
/*
*控制访问表
* acl值 功能
* 1 需要登录
* 2 自身修改
* 4 需要组的权限集合
* 8 需要身份访问集合
* 16 身份被禁止访问
* 32 可访问的日期
* 64 可访问的周日
* 128 可访问的时间
* 256 输入密码才能访问
* 512 超级管理使用
*/
class aclACL extends acl {
public $routername="acl";
public $aclid='2'; //权限资源ID,如果登录人员没有拥用这个权限那么其(下面)它值都为0也不能访问
public $roledisable=array(9); //禁用身份
public $pwd=123456; //密码访问 ACL->noPwd();
public $date=array('begin'=>0,'end'=>0); //允许日期之间
public $hours=array('begin'=>0,'end'=>0); //一日内小时区间
public $weeks=array('begin'=>0,'end'=>0); //一周内周一到周七
public $aclgroup=array("create"=>"4,45,8"); //create需要的组才能创建
public $aclrole=array("all"=>"6","create"=>"7,95,78"); //create需要的角色才能创建,该组需要ID为6的角色才能访问
public $acl=array("all"=>0,
"index"=>4, //表列4表示检查组的组合
"delete"=>1, //删除只登录后删除,当然呆以设置为2或4
"update"=>1, //更新提交只能登录后才能更新,在这里做也防止非法、post,edit是不能访问显示编辑内容页
"createForm"=>1, //也不能新提交数据库
"edit"=>0, //登录才显示编辑框
"show"=>0, //不用登录也能显示
"create"=>1); //创新表单需要登录操作 可以设置某个组才能创建 } ?> 这个是要认证的文件模块是acl
每当用户访问acl模块时候,如果开启了认证那么会调用这个类
然后这个类会根据$acl 的all或index等值去做认证检查。
把这个文件放在router/acl目录里面就可以了,框架会自动认证如果用户没有相应的正向授权是无法访问相应的限制的。
比如crud create方法 负向权限为17 那按照前面解释应该是 需要登录和组授权 就是$aclgroup 数组中create的4 45 8三个组,
首先会员没有登录将提示登录,如果会员不在这三个组是无法访问该方法的会提示没有权限。目前router可以自己根据情况开启用acl控制
方法是在xxxxRouter.class.php文件中 添加 public function isAcl(){}
可以返回权限文件名比如返回curd,那么自动会调用curdACL.class.php类和名
curdRouter类设置验证
<?php
class curdRouter extends controller{
//返回 RBAC 控制访问列表验证类默认是跟router同名也就是curd
//可以不写这个函数,那么不会启用通用权限系统。
public function isAcl(){}
public function index()
{
$booktype=M("booktype");
$this->pager=C("pager");//取得分类
$this->pager->setPager($booktype->count(),10,'page');//取得数据总数中,设置每页为10
$this->assign("list",$booktype->orderby("bookid desc")->limit($this->pager->offset(),10)->fetch()->getRecord());
}
public function login(){ //登录页面
}
public function logout(){ //退出页面 MY()->logout(); //退出登录
redirect(url_for("guestbook/index"),"退出成功",3);
}
public function noAcl($mask) { //处理一下如果没有权限转向登录
redirect(url_for("guestbook/login"),"需要登录",3);
}
public function loginpost() { //登录提交地方 简单处理下登录认证
if($_POST['author']=='queryphp'&&md5($_POST['pwd'])==md5('123456'))
{
MY()->setLogin(); //设置登录状态
redirect(url_for("guestbook/adminlist"),"登录成功",3);
}
redirect(url_for("guestbook/login"),"登录失败",3);
}
<?php
/*
*登录信息基本类
*权限表可以缓存数据,登录时候恢复。
*/
class mybase {
public $options=array();
public $uid;
public $username;
public $isadmin;
public $role=array(); //我使用的身份
public $group=array(); //我所在组
public $grouprole=array(); //组的身份
public $mygroupMar=array(); //我拥有管理的组
public $mygroupOwn=array(); //属于我的组
public $acl=array(); //主动控制表 groupacl和myacl控制权限集合 内容是rbac的rbacid
public $groupacl=array(); //组拥用的控制权限
public $myacl=array(); //我的身份拥用的控制权限
public $loginfaild=0; //登录失败次数 如果超过这个数应该禁止IP登录几分种
这是基本
可以把myUser.class.php放在项目lib目录里面
<?php
class myUser extends mybase {
}
?>
使用MY()函数就可以取得myUser了。
# 5.2 认证(Authentication):提供用户证个人觉得是有两种模式,区别在验证和设置上。一种方式是设置权限集中在后台,如数据库;验证权限集中在权限树,如cake和zend,检查时只帮两个:一,是否登录;二是否允许。 而不查是否有这个那个权限。第二种可能和你的一样了。即你的检查移到了前台:这个模块需要哪些权限?要模块里设定.无论哪个,权限系统要清晰,健壮,适用仅作参考
目前我这个前后台都可以
个人登录后会把权限数据查出来 个人权限是ID,这个ID会跟模块ID在一起
你访问那个模块,那个模块他自己也有自己的权限访问 在后台可以设置,因为我权限是存ID
不过没怎么看清楚,
比如前台一篇文章,
对于user1,需要登陆且输入密码
对于user2,可直接察看。
你是如何设置的呢?还有一个问题是,对于复杂点的应用
public $acl=array("all"=>0,
"index"=>4, //表列4表示检查组的组合
"delete"=>1, //删除只登录后删除,当然呆以设置为2或4
"update"=>1, //更新提交只能登录后才能更新,在这里做也防止非法、post,edit是不能访问显示编辑内容页
"createForm"=>1, //也不能新提交数据库
"edit"=>0, //登录才显示编辑框
"show"=>0, //不用登录也能显示
"create"=>1); //创新表单需要登录操作 可以设置某个组才能创建
这么些个权限可能不够用,比如同样是create,我在同一个模块页面可能有create资源1的权限,但是没有create资源2的权限,如何设置?
比如一个报表模块,假设要做导出动作,url是这样的
1./yourframework/report/create/pdf/1,
2./yourframework/report/create/excel/1
现在有个用户具有导出pdf的权限,但是没有导出excel的权限。如何设置呢?
对于user1,需要登陆且输入密码
对于user2,可直接察看。
-------------------------------------------
这个问题我还没想到,那是不是可以设置一组免密码身份
我是不是设置一组免密码通过的
这么些个权限可能不够用,比如同样是create,我在同一个模块页面可能有create资源1的权限,但是没有create资源2的权限,如何设置?
------------------------------------------
这个可以的,一个模块一个xxxxACL.class.php文件,里面都有方法和all设置
1./yourframework/report/create/pdf/1,
2./yourframework/report/create/excel/1
现在有个用户具有导出pdf的权限,但是没有导出excel的权限。如何设置呢?这个很简单,建两个身份,一个身分是有导出pdf文件权限,一个身份是有导出excel文件权限
user1 是有pdf导出身份
user2 设置有导出excel身份
user3 设置有pdf和excel导出身份
发布,有些ORM文档还没有写,我想再写一篇可以独立使用通用权限系统的。
因为这个权限不一定要集成在框架里面
就像现实中,他是这个办公室部门的,那么他有这个部门身份权限
他可以是多个部门的,那么他有多个部门身分权限这个从组继承来
二个是管理员可以给他设置身份,他可以保持有这个身份。用户登录时候会用他的ID去查组的身份,然后取回他所在组的身份权限
然后是再去取个人身份表属于自己的身份,然后两个身份合并,因为可能有重复身份
然后再用总身份去取得权限资源表里面的权限回来,这样一个用户有了一个权限资源表了。有了权限资源表,可以去访问资源了,比如访问curd程序模块pdf方法。如果自己权限资源
没有curd程序模块pdf方法这个ID,是不能方问的。因为curd程序模块pdf方法在资源表里面
注册了一行,是有一个ID值的。如果用户有curd程序模块pdf方法ID,也可以访问了。现在只是能够访问而已,
如果curd程序模块pdf方法还设置了时间或日期,如果不在设置的时间或日期间也不能访问如果curd程序模块pdf方法设置了要组合身份或组的组合
比如必需要有导出pdf和excel身份才能访问那么,和用户有pdf权限也不能访问。会提示权限不够
那为什么用户有了pdf权限按理应该说可以导出pdf文件了,为什么还要设置一个关卡。
设计意思是因为有些人可能有交叉身份。比如我这A组有导出pdf身份,同时A组还有一个导出excel身份
但是A组里面如果都全是A组的人马都有这两个功能,现在你虽然有A组权限但是你只有一个pdf权限
现在A组为了保证是A组人员才行,所以设置了必需要pdf和excel身份还有必需是A组组员。
------------------------
每个程序类都有一个xxxACL.class.php文件对应,如果没有就没有权限
每个程序类的xxxACL.clas.php文件acl都有一个all键值,如果找不到对应的方法权限值
那么会默认使用all值。
程序如下实现 if(!isset($this->acl[$action])){ //如果没有定义方法权限值
if($this->acl['all']!=0) //使用方all值
{
$this->acl[$action]=$this->acl['all']; //取得all值
$action='all'; //把$acton方法也使用all
}else{
Return true;//如果都是0返回 //如果又不定义$action方法,all值也是为0说明 程序模块不需要保护
}
}
if($this->acl[$action]==0){
Return true; //如果设置了$action方法为0说明不用保护,就算all为512也不用保护
}
/***
精简版迷你型,用户权限管理系统.
用户 角色 权限名称 [用户角色关系] [角色权限关系]
1 登陆时,读取用户所对应的角色,通过角色获取用户拥有的权限.
*/
if (sizeof($rows) === 1) { //如果用户名和密码正确
//取得用户的权限
if ((string)$rows[0]->user_role !== '0') { //如果用户设置了角色
$role_model_name = CS_get_model_name('roles');
$this->load->model($role_model_name);
$role_row = $this->$role_model_name->row($rows[0]->user_role);
if ($role_row->roles_permissions != '') { //如果角色设置了权限
$rows[0]->user_permissions = explode(',', $role_row->roles_permissions);
} else {
$rows[0]->user_permissions = array();
}
} else {
$rows[0]->user_permissions = array();
}/**
当哪里需求使用相应的权限时,用CS_check_permissions($access_name) 判断用户是否有相应的权限。
*/
/**
* 判断用户是否拥有指定的权限
*
* @param string $access_name 权限名称
*/
function CS_check_permissions($access_name) {
if (CS_is_login()) { //如果已经登录
return in_array($access_name, $_SESSION['admin_user_data']->user_permissions) || $_SESSION['admin_user_data']->user_id == '1';
}
}//这个比较小,比较简单,在小型项目和不特别严重的权限体系中,我个人比较喜欢还有一次,为一个单位设计权限相关的东西时,对很多流程要进行权限,当时我想出了树形结构遍历,去整权限,再配合一些临时授权。
我就是要避免在程序中使用这种判断程序
这种样子又不够灵活
你的google code里的中文文件能否都放个utf8版本?
在google code svn的browse里没法直接看
刚看下还真有些php文件是ansi格式可以使用json存起来如果要解决一个模块下的子模块权限问题
添加一行就可以了
比如:
public $acl=array("all"=>0,
"index"=>4, //表列4表示检查组的组合
添加一行显示show方法权限
public $acl=array("all"=>0,
"index"=>4, //表列4表示检查组的组合
"show"=>4, //表列4表示检查组的组合
这个也要加一个ID值
public $aclid=array(2,3); //权限资源ID,如果登录人员没有拥用这个权限那么其(下面)它值都为0也不能访问
比如show 在rabc表中ID是3 因为这个在访问时候会检查,比如用户没有这个ID权限是访问不了的
CS_check_permissions是统一的公用权限判定接口函数,函数内可以预先判定一个公用配置值,来决定是否开启权限判定功能,不一定非要删除代码嘛,而且结合mvc代码结构,也可以在url router阶段未进入controller之前就预先判定好权限呀,我想对于你的框架来说,也应该提供一个这样的函数,动态化 + 特殊化 = 扩展性 嘛
而且我觉得权限的指定对于一个产品来说,是应该使用产品的管理员去指定的,而不是开发人员,你的框架如果真正应用于一个产品,对于权限的配置,目前阶段是否可以比较容易的结合后台管理呢?比如你的每个模块的xxxACL.class文件,是否可以考虑通过后台权限管理模块生成,而真正的用户的权限数据到时候是需要数据库也有一份的,这样才方便后台管理。
我前面是做演示,在因为后台还没有做好,所以产前面为什么要加ID,而不是使用什么名字之类我的数据库设置如下
粗略看了一下。
project是各级模块吗?rbac表里的parentid是什么意思呢?
project是项目文件,比如
/project
/admin
/front
都是项目,项目中可能有相同的模块
rbac是模块注册表 如果在这里注册了,会生成xxxACL.class.php文件
parentid是父ID,也是说每个方法的父ID是模块名。模块名对就的权限是all设置,就是xxxACL.class.php文件中的all设置。这样如果没有定义方法就按all来设置
提个建议,前面就想说一下,rbac里面的那些个timestart,timeend,daystart...这些东西看起来是扩展性需求比较大,为何不把它们全部整合成一个text字段,json格式也行
{
'timestart': '...'
,'timeend' : '...'
}
默认给一组设置,这样注册时需要添加一项或者去除一项都不需要动字段,只需要添加或去除表单,最终生成一个json串存回去。
还有到时候后台理应可管理各个project的各个模块的,所以我觉得rbac把模块分离出去比较好.rbac表再去关联模块表
这个project是项目 curd 是模块 index是方法
先发布一版,可以先预览下通用权限系统
最新程序可下到google 下载
http://code.google.com/p/queryphp/downloads/list
演示地址
这样可以根据什么样的模块权限显示什么样的内容。原理是 拥用这个模型的权限才显示里面的内容。只是要求权限文件一定要用程序能搜索到
目前只搜索框架目录module下面有没有权限文件