ThinkCMF中的权限是以后台菜单为基础来进行设置的(menu table),即如果你需要一个自定义的权限,那么你需要在后台菜单里添加一项菜单,然后在角色管理里可以针对角色进行授权
 
而现在遇到一个需求:管理员可以自行选择哪些用户可以查看某些分类(除了几个指定分类外其他分类都是公开的)
因为我这里的用户其实就是相当于不同的管理员,所以我就直接把权限问题整合到了现有的“角色授权”功能里
因为(只有几个分类需要授权,所以我将这些分类都移到一个一级分类里"内网登录"
然后在后台角色授权(RbacController)里直接对该分类及子分类进行处理(该分类ID保存在配置文件中AUTHORIZE_CATID)
 
\application\Admin\Controller\RbacController.class.php 中添加了对分类进行授权的功能
/**
* 角色授权
*/
public function authorize() {
$this->auth_access_model = D("Common/AuthAccess");
//角色ID
$roleid = intval(I("get.id"));
if (!$roleid) {
$this->error("参数错误!");
}
import("Tree");
$menu = new \Tree();
$menu->icon = array('│ ', '├─ ', '└─ ');
$menu->nbsp = ' ';
$result = $this->initMenu();
$newmenus=array();
$priv_data=$this->auth_access_model->where(array("role_id"=>$roleid))->getField("rule_name",true);//获取权限表数据
foreach ($result as $m){
$newmenus[$m['id']]=$m;
}
foreach ($result as $n => $t) {
$result[$n]['checked'] = ($this->_is_checked($t, $roleid, $priv_data)) ? ' checked' : '';
$result[$n]['level'] = $this->_get_level($t['id'], $newmenus);
$result[$n]['parentid_node'] = ($t['parentid']) ? ' class="child-of-node-' . $t['parentid'] . '"' : '';
}
$str = "<tr id='node-\$id' \$parentid_node>
<td style='padding-left:30px;'>\$spacer<input type='checkbox' name='menuid[]' value='\$id' level='\$level' \$checked onclick='javascript:checknode(this);'> \$name</td>
</tr>";
$menu->init($result);
$categorys = $menu->get_tree(0, $str);
//需要授权的分类列表
$categorys.= $this->_authorize_cat($priv_data); $this->assign("categorys", $categorys);
$this->assign("roleid", $roleid);
$this->display();
}
/**
* 角色授权
*/
public function authorize_post() {
$this->auth_access_model = D("Common/AuthAccess");
if (IS_POST) {
$roleid = intval(I("post.roleid"));
if(!$roleid){
$this->error("需要授权的角色不存在!");
}
if (is_array($_POST['menuid']) && count($_POST['menuid'])>0) {
$menu_model=M("Menu");
$auth_rule_model=M("AuthRule");
$this->_authorize_post_cat($_POST['catid'],$roleid);          $this->auth_access_model->where(array("role_id"=>$roleid,'type'=>'admin_url'))->delete();
foreach ($_POST['menuid'] as $menuid) {
$menu=$menu_model->where(array("id"=>$menuid))->field("app,model,action")->find();
if($menu){
$app=$menu['app'];
$model=$menu['model'];
$action=$menu['action'];
$name=strtolower("$app/$model/$action");
$this->auth_access_model->add(array("role_id"=>$roleid,"rule_name"=>$name,'type'=>'admin_url'));
}
}
$this->success("授权成功!", U("Rbac/index"));
}else{
//当没有数据时,清除当前角色授权
$this->auth_access_model->where(array("role_id" => $roleid))->delete();
$this->error("没有接收到数据,执行清除授权成功!");
}
}
}
/**
* 角色授权-支持指定分类
* @Author HTL
* @DateTime 2016-08-10T10:20:01+0800
* @param string $priv_data[auth_access table data]
* @return [type] [description]
*/
function _authorize_cat($priv_data)
{
$cat_id = intval(C("AUTHORIZE_CATID"));//from config.php ,该分类必须是一级分类
if($cat_id<=0) return; $cats = M("Terms")->where("status=1 and path like '%0-$cat_id%'")->order("parent,listorder,term_id")->getField("term_id as id,name,parent,path",true);
if(!cats || count($cats)<=0) return;
$cat_html = "";//生成的html
//根据不同level生成不同层级效果
$level_spacer = array('',' ├─' ,' │ ├─ ',' │ │ └─ ' );
$str = "<tr id='cat-#id#' #parentid_node#>
<td style='padding-left:30px;'>#spacer#<input type='checkbox' name='catid[]' value='#id#' level='#level#' #checked# onclick='javascript:checknode(this);'> #name#</td>
</tr>";
foreach ($cats as $key => $value) {
$checked = in_array($value['id'],$priv_data)?"checked":""; //权限中是否已经存在该分类id
$level = count(explode('-',$value['path']))-2; //减2是因为:要去掉数据库中的0-不算和explode方法是从1开始的
$parentid_node = ($value['parent']) ? ' class="child-of-cat-' . $value['parent'] . '"' : '';//父类
$_str = str_replace('#id#',$value['id'],$str);
$_str = str_replace("#spacer#",$level_spacer[$level],$_str);
$_str = str_replace("#level#",$level,$_str);
$_str = str_replace("#checked#",$checked,$_str);
$_str = str_replace("#parentid_node#",$parentid_node,$_str);
$_str = str_replace("#name#",$value['name'],$_str);
$cat_html .= $_str;
}
return '<tr><td><br></td></tr>'.$cat_html;
}
/**
* 将选择的分类保存到权限表中
* @Author HTL
* @DateTime 2016-08-10T11:45:48+0800
* @param [type] $catids [post catids]
* @param [type] $roleid [current user roleid]
* @return [type] [description]
*/
function _authorize_post_cat($catids,$roleid)
{
if(!$catids || count($catids)<=0 || $roleid<=0) return;
//使用单独的type(cat_url)进行区分
$this->auth_access_model->where(array("role_id"=>$roleid,'type'=>'cat_url'))->delete();
foreach ($catids as $catid) {
$this->auth_access_model->add(array("role_id"=>$roleid,"rule_name"=>$catid,'type'=>'cat_url'));
}
}
 
\data\conf\config.php 中定义一个配置项,并指定一级分类ID
<?php return array (
'AUTHORIZE_CATID' => 30,/*需要授权才能访问的一级分类ID(自动包括所有子分类),必须是一级分类*/
);?>
 
修改后的角色授权页面

保存后的数据库信息(cmf_auth_access)

 
 
2016-08-11 update:
 
之前没有考虑一个问题是:在添加或编辑文章时如果管理员对文章同时选择了有权限的分类和没有权限的分类,那这种情况权限不就没有用了吗?
 
下面是我的解决办法,即在保存文章时去判断是否同时选择了有权限和无权限的分类,如果有则不能进行保存操作,
 
 
 
\application\Portal\Controller\AdminPostController.class.php
/**
* 在显示模板之前调用此方法 $this->get_authority_cats();,用于前端处理
* 获取需要权限的所有分类
* 用于防止管理员同时选择有权限的分类和没有权限的分类
* @AuthorHTL
* @DateTime 2016-08-11T11:01:49+0800
* @param boolean $is_view [是否在页面上展示,default=true]
* @return [type] [description]
*/
function get_authority_cats($is_view = true)
{
$cat_id = intval(C("AUTHORIZE_CATID"));//需要权限的一级
if($cat_id<=0) return;
$cats = M("Terms")->where("status=1 and path like '%0-$cat_id%'")->order("parent,listorder,term_id")->getField("term_id",true);
if($is_view){
$this->assign("authrize_cats",implode(",",$cats));
}
else{
return $cats;
}
}
/**
* 在保存文章之前调用此方法 $this->check_cats($_POST['term']),防止前端检测未执行或被人为绕过
* 检查文章的分类是否同时包含了有权限的和无权限的
* 要么选择的全部是有权限的
* 要么选择的全部是无权限的
* 不能混合选择
* @AuthorHTL
* @DateTime 2016-08-11T11:09:07+0800
* @param [type] $_POST [description]
* @return [type] [description]
*/
function check_cats($post_cats)
{
if(!$post_cats || count($post_cats)<=0) return;
$first_result = ture;
$auth_cats = $this->get_authority_cats(false);
if(!$auth_cats || count($auth_cats)<=0) return;
foreach ($post_cats as $i=>$mterm_id){
//以首行的结果做比较基础
if($i<=0){
$first_result = false;//in_array($mterm_id, $auth_cats);
}
//如果跟首次的不同则说明包含有权限和没有权限的分类
else if($first_result != in_array($mterm_id,$auth_cats)){
$this->error("不能同时选择有权限的栏目和无权限的栏目!");
return false;
}
}
}
前端页面的脚本处理

/**
* 检查文章的分类是否同时包含了有权限的和无权限的
* 要么选择的全部是有权限的
* 要么选择的全部是无权限的
* 不能混合选择
* @AuthorHTL
* @DateTime 2016-08-11T10:41:05+0800
* @return {[type]} [description]
*/
function check_cat() {
var _term_vals = $("#term").val()//选择的栏目列表
,first_result = true//default value
,auth_cats = ',{$authrize_cats},';//有权限的栏目
//只有选择了一个分类或没有权限分类
if(_term_vals.length<=1 || auth_cats.length<=2) return true;
for(i in _term_vals){
//以首行的结果做比较基础
if(i<=0){
first_result = auth_cats.indexOf(","+_term_vals[i]+",")>=0;
}
//如果跟首次的不同则说明包含有权限和没有权限的分类
else if(first_result !== auth_cats.indexOf(","+_term_vals[i]+",")>=0){
alert("不能同时选择有权限的栏目和无权限的栏目!");
return false;
}
}
return true;
}
//提交前先检测
$(".J_ajax_submit_btn").click(function () {
return check_cat();
});
 

thinkcmf 角色授权支持分类的更多相关文章

  1. RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2->WinForm版本新增新的角色授权管理界面效率更高、更规范

    角色授权管理模块主要是对角色的相应权限进行集中设置.在角色权限管理模块中,管理员可以添加或移除指定角色所包含的用户.可以分配或授予指定角色的模块(菜单)的访问权限.可以收回或分配指定角色的操作(功能) ...

  2. Asp.Net Core 中IdentityServer4 实战之角色授权详解

    一.前言 前几篇文章分享了IdentityServer4密码模式的基本授权及自定义授权等方式,最近由于改造一个网关服务,用到了IdentityServer4的授权,改造过程中发现比较适合基于Role角 ...

  3. 【Java EE 学习 76 上】【数据采集系统第八天】【角色授权】【用户授权】【权限的粗粒度控制】【权限的细粒度控制】

    一.角色管理 单击导航栏上的"角色管理"超链接,跳转到角色管理界面,在该界面上显示所有角色,并提供角色的增加和删除.修改超链接. 1.增加新角色(角色授权) 流程:单击增加新角色超 ...

  4. jenkins之角色授权[六]

    标签(linux): jenkins 笔者Q:972581034 交流群:605799367.有任何疑问可与笔者或加群交流 有时候我们公司里面可能有好几个开发团队,当你做完jenkins后,对于测试环 ...

  5. RDIFramework.NET V3.3 WinForm版角色授权管理新增角色对操作权限项、模块起止生效日期的设置

    在实际应用在我们可能会有这样的需求,某个操作权限项(按钮)或菜单在某个时间范围内可以让指定角色访问.此时通过我们的角色权限扩展设置就可以办到. 在我们框架V3.3 WinForm版全新增加了角色权限扩 ...

  6. RDIFramework.NET V3.3 Web版角色授权管理新增角色对操作权限项、模块起止生效日期的设置

    在实际应用在我们可能会有这样的需求,某个操作权限项(按钮)或菜单在某个时间范围内可以让指定角色访问.此时通过我们的角色权限扩展设置就可以办到. 在我们框架V3.3 Web版本全新增加了角色权限扩展设置 ...

  7. RDIFramework.NET ━ .NET快速信息化系统开发框架 V3.2->Web版本新增新的角色授权管理界面效率更高、更规范

    角色授权管理模块主要是对角色的相应权限进行集中设置.在角色权限管理模块中,管理员可以添加或移除指定角色所包含的用户.可以分配或授予指定角色的模块(菜单)的访问权限.可以收回或分配指定角色的操作(功能) ...

  8. jenkins按角色授权

    当一个公司的开发分为多个组或者是多个项目时,不能让所有的开发都公用一个构建,否则将会变得很混乱,为了解决这一问题,jenkins提供了角色授权的机制.每个开发有着对应的账号和权限,可以自行新建.构建. ...

  9. CZGL.Auth: ASP.NET Core Jwt角色授权快速配置库

    CZGL.Auth CZGL.Auth 是一个基于 Jwt 实现的快速角色授权库,ASP.Net Core 的 Identity 默认的授权是 Cookie.而 Jwt 授权只提供了基础实现和接口,需 ...

随机推荐

  1. Fiddler 实现手机的抓包

    Fiddler是我最喜爱的工具,几乎每天都用, 我已经用了8年了. 至今我也只学会其中大概50%的功能. Fiddler绝对称得上是"神器", 任何一个搞IT的人都得着的. 小弟我 ...

  2. SGU 275. To xor or not to xor (高斯消元法)

    题目链接:http://acm.sgu.ru/problem.php?contest=0&problem=275 题意:给你n个数,可以选择任意个数异或,但是要使得最后的异或值最大. 我们把每 ...

  3. SQL Server、Oracle和MySQL中查出值为NULL的替换

    参考文献: http://database.51cto.com/art/200803/67397.htm 正文 在SQL Server Oracle MySQL当数据库中查出某值为NULL怎么办? 1 ...

  4. Setting an Event to Null

    I have a code like this: public class SomeClass { int _processProgress; public int ProcessProgress { ...

  5. Modbus读写模拟量寄存器具体解释

    读可读写模拟量寄存器: 发送命令(主机向从机)格式: [设备地址] [命令号03] [起始寄存器地址高8位] [低8位] [读取的寄存器数高8位] [低8位] [CRC校验的低8位] [CRC校验的高 ...

  6. 内存加载DLL

    1.前言 目前很多敏感和重要的DLL(Dynamic-link library) 都没有提供静态版本供编译器进行静态连接(.lib文件),即使提供了静态版本也因为兼容性问题导致无法使用,而只提供DLL ...

  7. HelloWorld 之JasperReports初步

    在企业应用系统中,经常要输出各种格式的数据报表. 著名的开源项目<JasperReports可以很好的解决这个问题. 使用JasperReports可以在预先设定好格式的报表基础上进行数据的填充 ...

  8. WordPress主题开发:网站搜索

    调用方法一:手动输入html <form role="search" method="get" id="searchform" act ...

  9. ASP.NET MVC:some benefits of asp.net mvc

    Full control over HTML Full control over URLs Better separation of concerns Extensibility Testabilit ...

  10. Android之2次打开添加友盟统计代码,后缀会添加广告

    这里首先列明步骤, 做一个标识仅此而已. 1. 首先使用apktool来反编译你待需要加入友盟统计的apk包, 具体如何使用与配置apktool, 请参考我关于apktool配置的文章. 2. 然后自 ...