权限管理

在开发中经常需要用来权限管理,cmlphp中提供了权限控制类,\Cml\Vendor\Acl。这边对使用进行说明。

数据库建表

Acl类依赖的数据表如下,请复制到mysql中执行。 语句中的pr_为表前缀,请自行替换在实际的表前缀。

  1. 建库语句
  2. CREATE TABLE `pr_admin_app` (
  3. `id` smallint(6) unsigned NOT NULL AUTO_INCREMENT,
  4. `name` varchar(255) NOT NULL DEFAULT '' COMMENT '应用名',
  5. PRIMARY KEY (`id`)
  6. ) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4;
  7. CREATE TABLE `pr_admin_access` (
  8. `id` int(11) NOT NULL AUTO_INCREMENT COMMENT '权限ID',
  9. `userid` int(11) DEFAULT '0' COMMENT '所属用户权限ID',
  10. `groupid` int(11) DEFAULT '0' COMMENT '所属群组权限ID',
  11. `menuid` int(11) NOT NULL DEFAULT '0' COMMENT '权限模块ID',
  12. PRIMARY KEY (`id`),
  13. KEY `idx_userid` (`userid`) USING BTREE,
  14. KEY `idx_groupid` (`groupid`) USING BTREE,
  15. KEY `idx_menuid` (`menuid`) USING BTREE
  16. ) ENGINE=MyISAM AUTO_INCREMENT=190 DEFAULT CHARSET=utf8mb4 COMMENT='用户或者用户组权限记录';
  17. CREATE TABLE `pr_admin_groups` (
  18. `id` smallint(3) unsigned NOT NULL AUTO_INCREMENT,
  19. `name` varchar(150) DEFAULT NULL,
  20. `status` tinyint(1) unsigned DEFAULT '1' COMMENT '1正常,0删除',
  21. `remark` text NOT NULL,
  22. PRIMARY KEY (`id`)
  23. ) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4;
  24. CREATE TABLE `pr_admin_menus` (
  25. `id` int(11) NOT NULL AUTO_INCREMENT,
  26. `pid` int(11) NOT NULL DEFAULT '0' COMMENT '父模块ID编号 0则为顶级模块',
  27. `title` char(64) NOT NULL COMMENT '标题',
  28. `url` char(64) NOT NULL COMMENT 'url路径',
  29. `isshow` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否显示',
  30. `sort` smallint(3) unsigned NOT NULL DEFAULT '0' COMMENT '排序倒序',
  31. `app` smallint(6) unsigned NOT NULL DEFAULT '0' COMMENT '菜单所属app,对应app表中的主键',
  32. `params` varchar(64) NOT NULL DEFAULT '' COMMENT 'url参数',
  33. PRIMARY KEY (`id`),
  34. KEY `idex_pid` (`pid`) USING BTREE,
  35. KEY `idex_order` (`sort`) USING BTREE,
  36. KEY `idx_action` (`url`)
  37. ) ENGINE=MyISAM AUTO_INCREMENT=55 DEFAULT CHARSET=utf8mb4 COMMENT='权限模块信息表';
  38. CREATE TABLE `pr_admin_users` (
  39. `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  40. `groupid` varchar(255) NOT NULL DEFAULT '0',
  41. `username` varchar(40) NOT NULL DEFAULT '',
  42. `nickname` varchar(50) DEFAULT NULL COMMENT '昵称',
  43. `password` char(32) NOT NULL DEFAULT '',
  44. `lastlogin` int(10) unsigned NOT NULL DEFAULT '0',
  45. `ctime` int(10) unsigned NOT NULL DEFAULT '0',
  46. `stime` int(10) unsigned NOT NULL DEFAULT '0',
  47. `status` tinyint(1) unsigned DEFAULT '1' COMMENT '1正常,0删除',
  48. `remark` text NOT NULL,
  49. `from_type` tinyint(3) unsigned DEFAULT '1' COMMENT '用户类型。1为系统用户。',
  50. PRIMARY KEY (`id`),
  51. UNIQUE KEY `username` (`username`)
  52. ) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4;

数据表说明

  • pr_admin_group为用户组表

用来存储用户组相关信息。

  • pr_admin_users为用户信息表

用来存储用户相关信息。一个用户可能属于多个用户组,比如某个用户同时属于id为 1、3的用户组。则用户表中的groupid字段存储的数据则为 1|3。多个组id以|分隔

  • pr_admin_menu为菜单表

用来存储菜单相关信息。数据格式类似  权限管理  - 图1
url字段为访问的操作的地址

  • pr_admin_access为权限关系表

用来存储权限相关信息。

  • pr_admin_app为应用表

用来存储应用相关信息,app表和权限管理无关只是用来更细粒度的管理我们的菜单。

修改配置

在配置文件中加入如下配置:'administratorid'=> 1, //超管理员id

这边的1是指pr_admin_users表中的id。这个配置的作用是标识id为1的用户为超级管理员。 超级管理员默认拥有所有权限

在php中使用

  • 保存登录信息

  1. <?php
  2. use Cml\Vendor\Acl;
  3. //判断用户名密码....登录是否成功
  4. //登录成功后保存用户登录信息
  5. Acl::setEncryptKey('ffddsff');//配置加密key 这个最好在共公控制器的init方法/__construct方法里设置
  6. Acl::setLoginStatus($user['id']); //设置某用户为登录判断
  • 判断用户是否已登录以及是否有权限

  1. <?php
  2. use Cml\Vendor\Acl;
  3. $user = Acl::getLoginInfo();
  4. if (!$user) {//未登录
  5. //提示用户登录
  6. }
  7. if (!Acl::checkAcl($this)) {//无权限
  8. //提示用户没没权限
  9. }
  • 获取当前登录用户有权限的菜单

  1. <?php
  2. use Cml\Vendor\Acl;
  3. $menus = Acl::getMenus();//包含用户自有的权限、以及其所在用户组所拥有的权限
  • 登出

  1. <?php
  2. use Cml\Vendor\Acl;
  3. Acl::logout();//包含用户自有的权限、以及其所在用户组所拥有的权限
  • 判断当前用户是否是超级管理员

  1. <?php
  2. use Cml\Vendor\Acl;
  3. $isSuperUser = Acl::isSuperUser();
  • 自定义表名

如果想要自定义表名可以如下操作:

Acl::setTableName([
'access' => 'admin_access',
'groups' => 'admin_groups',
'menus' => 'admin_menus',
'users' => 'admin_users',
]);

app

特殊说明

通常情况我们会建一个共用的控制器。在共用控制器的init方法或__construct方法里,验证用户是否登录以及是否拥有当前模块的访问权限。这时是所有对外的方法都会被验证。但是在实际项目中我们往往会想要跳过一些方法的权限校验,比如:

我们有个用户管理。用户管理有- add 方法用来渲染输出用户添加表单。- edit 方法用来渲染编辑用户资料的表单。- save 方法用来接收 add以及edit这两个页面提交过来的数据。

按照正常流程我们需要添加三个菜单分别是 user/adduser/edituser/save三条记录到pr_admin_menu表。然后给用户授权的时候如果只给添加权限,也必须添加add和save的记录到pr_admin_access表中或者是只添加add记录然后在save方法中判断有无add的权限。这样是非常不方便的。所以在cmlphp中提供了两个偷懒的方法。

  • 对方法注释 @noacl 则不检查该方法的权限

比如有一个方法resume.想要跳过权限检查则注释如下即可

/**

  • 恢复微博
  • @noacl
    /
    public function resume()
  • 对方法注释 @acljump web/User/add 则将当前方法的权限检查跳转为检查 web/User/add方法的权限

比如上面说的 user/save权限只要判断有无user/add或user/edit的权限就好了。

/**

  • 保存用户信息
  • @acljump user/add|user/edit
    /
    public function save()
因为@noacl@acljump使用的是代码注解,所以php开启了opcache的话请配置 opcache.save_comments=1

模板中判断有无某个模块的权限

参考视图相关章节

示例

可参考示例后台项目

原文: http://doc.cmlphp.com/devintro/acl.html