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. 给Eclipse安装eUML2插件以及可能出现的依赖错误解决方案(转)

    eUML2是一款强大的,基于Eclipse应用程序的UML建模工具.开发者可以在UML开发过程中将模型转化为Java代码:确保软件质量和减少开发时间. 必备条件 Java runtime 1.5 or ...

  2. LPC43xx MCU PIN Name and GPIO PIN Name Table

    //--------------------------------------------------------------------------------+ // LPC43xx Pin N ...

  3. 《Go语言实战》摘录:6.2 并发 - goroutine

    6.2 goroutine

  4. [web.config]如何灵活使用配置文件

    摘要 在实际项目中,经常遇到比较多的环境,比如开发环境,测试环境,生产环境.对于这些环境,可能会有不同接口调用,不同的数据库连接字符串等等.那么该如何实现不同环境的参数快速切换呢?当然,最笨的方式就是 ...

  5. C#中泛型容器Stack<T>的用法,以及借此实现”撤销/重做”功能

    .Net为我们提供了众多的泛型集合.比如,Stack<T>先进后出,Queue<T>先进先出,List<T>集合元素可排序,支持索引,LinkedList<T ...

  6. Delphi 局域网点对点文件传输(IdTcpClient控件)

    unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms ...

  7. Execute Javascript in iOS Applications

    In this tutorial, I have covered How to execute JavaScript in iOS / Objective-C. You can execute Jav ...

  8. 【POI】maven引用POI的依赖,XSSFWorkbook依旧无法使用的问题。

    maven项目引用POI的jar: <!-- https://mvnrepository.com/artifact/org.apache.poi/poi --> <dependenc ...

  9. SurfaceFlinger( 226): Permission Denial: can't access SurfaceFlinger

    MODIFY_PHONE_STATE permission is granted to system apps only. For your information, there are 2 type ...

  10. 使用android 隐藏类和方法

    在应用程序中添加与android.jar包相同的包目录,添加要隐藏类和方法.保证能编译通过就可以.