权限管理

在开发中经常需要用来权限管理,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/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/adduser/edit的权限就好了。

    /**
    * 保存用户信息
    * @acljump user/add|user/edit
    *
    */
    public function save()

因为@noacl@acljump使用的是代码注解,所以php开启了opcache的话请配置 opcache.save_comments=1

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

参考视图相关章节

示例

可参考示例后台项目

results matching ""

    No results matching ""