权限管理
在开发中经常需要用来权限管理,cmlphp中提供了权限控制类,\Cml\Vendor\Acl
。这边对使用进行说明。
数据库建表
Acl
类依赖的数据表如下,请复制到mysql中执行。 语句中的pr_
为表前缀,请自行替换在实际的表前缀。
建库语句
CREATE TABLE `pr_admin_app` (
`id` smallint(6) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL DEFAULT '' COMMENT '应用名',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `pr_admin_access` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '权限ID',
`userid` int(11) DEFAULT '0' COMMENT '所属用户权限ID',
`groupid` int(11) DEFAULT '0' COMMENT '所属群组权限ID',
`menuid` int(11) NOT NULL DEFAULT '0' COMMENT '权限模块ID',
PRIMARY KEY (`id`),
KEY `idx_userid` (`userid`) USING BTREE,
KEY `idx_groupid` (`groupid`) USING BTREE,
KEY `idx_menuid` (`menuid`) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=190 DEFAULT CHARSET=utf8mb4 COMMENT='用户或者用户组权限记录';
CREATE TABLE `pr_admin_groups` (
`id` smallint(3) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(150) DEFAULT NULL,
`status` tinyint(1) unsigned DEFAULT '1' COMMENT '1正常,0删除',
`remark` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4;
CREATE TABLE `pr_admin_menus` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`pid` int(11) NOT NULL DEFAULT '0' COMMENT '父模块ID编号 0则为顶级模块',
`title` char(64) NOT NULL COMMENT '标题',
`url` char(64) NOT NULL COMMENT 'url路径',
`isshow` tinyint(1) NOT NULL DEFAULT '1' COMMENT '是否显示',
`sort` smallint(3) unsigned NOT NULL DEFAULT '0' COMMENT '排序倒序',
`app` smallint(6) unsigned NOT NULL DEFAULT '0' COMMENT '菜单所属app,对应app表中的主键',
`params` varchar(64) NOT NULL DEFAULT '' COMMENT 'url参数',
PRIMARY KEY (`id`),
KEY `idex_pid` (`pid`) USING BTREE,
KEY `idex_order` (`sort`) USING BTREE,
KEY `idx_action` (`url`)
) ENGINE=MyISAM AUTO_INCREMENT=55 DEFAULT CHARSET=utf8mb4 COMMENT='权限模块信息表';
CREATE TABLE `pr_admin_users` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`groupid` varchar(255) NOT NULL DEFAULT '0',
`username` varchar(40) NOT NULL DEFAULT '',
`nickname` varchar(50) DEFAULT NULL COMMENT '昵称',
`password` char(32) NOT NULL DEFAULT '',
`lastlogin` int(10) unsigned NOT NULL DEFAULT '0',
`ctime` int(10) unsigned NOT NULL DEFAULT '0',
`stime` int(10) unsigned NOT NULL DEFAULT '0',
`status` tinyint(1) unsigned DEFAULT '1' COMMENT '1正常,0删除',
`remark` text NOT NULL,
`from_type` tinyint(3) unsigned DEFAULT '1' COMMENT '用户类型。1为系统用户。',
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4;
数据表说明
- pr_admin_group为用户组表
用来存储用户组相关信息。
- pr_admin_users为用户信息表
用来存储用户相关信息。一个用户可能属于多个用户组,比如某个用户同时属于id为 1、3的用户组。则用户表中的groupid字段存储的数据则为 1|3。多个组id以|分隔
- pr_admin_menu为菜单表
用来存储菜单相关信息。数据格式类似
url字段为访问的操作的地址
- pr_admin_access为权限关系表
用来存储权限相关信息。
- pr_admin_app为应用表
用来存储应用相关信息,app表和权限管理无关只是用来更细粒度的管理我们的菜单。
修改配置
在配置文件中加入如下配置:'administratorid'=> 1, //超管理员id
这边的1是指pr_admin_users
表中的id
。这个配置的作用是标识id
为1的用户为超级管理员。 超级管理员默认拥有所有权限
在php中使用
<?php
use Cml\Vendor\Acl;
//判断用户名密码....登录是否成功
//登录成功后保存用户登录信息
Acl::setEncryptKey('ffddsff');//配置加密key 这个最好在共公控制器的init方法/__construct方法里设置
Acl::setLoginStatus($user['id']); //设置某用户为登录判断
<?php
use Cml\Vendor\Acl;
$user = Acl::getLoginInfo();
if (!$user) {//未登录
//提示用户登录
}
if (!Acl::checkAcl($this)) {//无权限
//提示用户没没权限
}
<?php
use Cml\Vendor\Acl;
$menus = Acl::getMenus();//包含用户自有的权限、以及其所在用户组所拥有的权限
<?php
use Cml\Vendor\Acl;
Acl::logout();//包含用户自有的权限、以及其所在用户组所拥有的权限
<?php
use Cml\Vendor\Acl;
$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/add
、 user/edit
、user/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
模板中判断有无某个模块的权限
参考视图相关章节
示例
可参考示例后台项目