原文已经不可考

一、什么是RBAC

基于角色的访问控制(Role-Based Access Control)作为传统访问控制(自主访问,强制访问)的有前景的代替受到广泛的关注。
在RBAC中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。
在一个组织中,角色是为了完成各种工作而创造,用户则依据它的责任和资格来被指派相应的角色,用户可以很容易地从一个角色被指派到另一个角色。角色可依新的需求和系统的合并而赋予新的权限,而权限也可根据需要而从某角色中回收。角色与角色的关系可以建立起来以囊括更广泛的客观情况。

二、ThinkPHP中的RBAC

先看下官方给的实例所用到的数据表,通过5张表实现权限控制,定义如下:
RBAC 要用到5个数据表

  1. think_user (用户表)
    [转] thinkphp 的 RBAC 权限验证 - 图1
  2. think_role (用户分组表)[有哪些角色,该角色与对应的userid用户相关联]
    [转] thinkphp 的 RBAC 权限验证 - 图2
  3. think_node (操作节点)
    代表有哪些应用-模块-模块方法,并且定义了之间的一种关系,比如noteid为30的是Public模块,noteid为31,32,33,34的方法add,insert,edit,update都属于Public。noteid为85的test方法,属于noteid为84的Game模块下的方法。
    [转] thinkphp 的 RBAC 权限验证 - 图3
  4. think_role_user (用户和用户分组的对应)
    根据用户表的id给出对应的角色id相关联,也就是给用户分配角色,比如userid为3的角色为2,根据role角色表,7代表员工的角色
    [转] thinkphp 的 RBAC 权限验证 - 图4
  5. think_access (各个操作和用户组的对应)
    权限表,比如角色id为2,也就是员工的权限,可以的对应的结点
    [转] thinkphp 的 RBAC 权限验证 - 图5

    三、config配置文件详解

    我们看看thinkphp官方示例中的config文件:
    1. array(
    2. 'APP_AUTOLOAD_PATH'=>'@.TagLib',
    3. 'SESSION_AUTO_START'=>true,
    4. 'USER_AUTH_ON' =>true,
    5. 'USER_AUTH_TYPE' =>1, // 默认认证类型 1 登录认证 2 实时认证
    6. 'USER_AUTH_KEY' =>'authId', // 用户认证SESSION标记
    7. 'ADMIN_AUTH_KEY' =>'administrator',
    8. 'USER_AUTH_MODEL' =>'User', // 默认验证数据表模型
    9. 'AUTH_PWD_ENCODER' =>'md5', // 用户认证密码加密方式
    10. 'USER_AUTH_GATEWAY' =>'/Public/login',// 默认认证网关
    11. 'NOT_AUTH_MODULE' =>'Public', // 默认无需认证模块
    12. 'REQUIRE_AUTH_MODULE' =>'', // 默认需要认证模块
    13. 'NOT_AUTH_ACTION' =>'', // 默认无需认证操作
    14. 'REQUIRE_AUTH_ACTION' =>'', // 默认需要认证操作
    15. 'GUEST_AUTH_ON' =>false, // 是否开启游客授权访问
    16. 'GUEST_AUTH_ID' =>0, // 游客的用户ID
    17. 'DB_LIKE_FIELDS' =>'title|remark',
    18. 'RBAC_ROLE_TABLE' =>'think_role',
    19. 'RBAC_USER_TABLE' =>'think_role_user',
    20. 'RBAC_ACCESS_TABLE' =>'think_access',
    21. 'RBAC_NODE_TABLE' =>'think_node',
    22. 'SHOW_PAGE_TRACE'=>1//显示调试信息
    23. );
    看注释就应该懂大半了,其中Public模块是无需认证的,道理很简单,没登录之前大家都是游客身份,如果登录页面也要权限,那从哪里登录呢?是吧,呵呵。默认网关地址就是认证失败,没有权限跳转到此处,重新登陆。ADMIN_AUTH_KEY表示超级管理员权限,如果你在user表建立一个名为admin的用户,那么这个用户就是超级管理员,不用给它分配权限,什么权限都有,为什么要设置一个这样的管理员,因为当你把权限分配错了容易引起系统权限混乱,搞得大家都访问不了,这时候超级管理员就来了。

    四、RBAC类的几个重要的方法

    authenticate($map,$model='')
    根据map中指定的条件查询“用户模型”,返回符合条件的数据。其实就是M(User)->where($map)->find()。
    saveAccessList($authId=null)
    检测当前用户的所有权限,并将这些拥有的权限保存在
    $_SESSION['_ACCESS_LIST'] 中,不返回任何东西。开销很大,是对RBAC::getAccessList的默认参数封装。
    传入用户的ID 此方法不返回值,只是设置 $_SESSION['_ACCESS_LIST'] 的值,其中包含了所有该用户对应的用户组的有权限操作的所有节点 $_SESSION['_ACCESS_LIST']['项目名']['模块名']['操作名'], 以后判断权限就是判断当前项目,模块和操作是否在 $_SESSION['_ACCESS_LIST']中能找到。
    getRecordAccessList($authId=null,$module='')
    检测当前用户在当前模块中所拥有的权限,并将这些权限返回。开销很大,是对getModuleAccessList的默认参数封装。
    checkAccess()
    检查当前操作是否需要认证,需要认证则返回true,不需要则返回false.
    checkLogin()
    检查用户是否登录。如果没有登录,则尝试进行“游客”登录;如果没有开启以游客身份登录,则跳转到认证网关。登录成功将返回true。
    AccessDecision($appName=APP_NAME)
    权限认证的过滤器方法,检查当前操作是否被允许,返回bool值。
    就是检测当前项目模块操作 是否在 $_SESSION['_ACCESS_LIST'] 数组中,也就是说 在 $_SESSION['_ACCESS_LIST'] 数组中 $_SESSION['_ACCESS_LIST']['当前操作']['当前模块']['当前操作'] 是否存在。如果存在表示有权限 否则返回flase。
    getAccessList($authId)
    取得指定用户的权限列表。
    getModuleAccessList($authId,$module)
    取得指定用户、指定模块的权限列表。