随着业务的不断发展,很多中小型公司都拥有了自己的用户维护系统,用户权限管理是其中重要的一环。为了保护系统中的敏感信息、保障业务的正常运行,我们需要使用角色权限管理机制,保证不同角色的用户只能访问指定的资源和数据。
本文将以ThinkPHP6框架为例,介绍如何使用其提供的权限控制中间件和扩展扩展包实现用户角色权限管理。
首先我们需要定义两个数据库表,一个是角色表,用来存储系统角色信息;另一个是权限表,用来存储系统权限信息。
CREATE TABLE role (
id int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
name varchar(20) NOT NULL COMMENT '角色名称',
description varchar(50) NOT NULL COMMENT '角色描述',
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
CREATE TABLE permission (
id int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
name varchar(20) NOT NULL COMMENT '权限名称',
description varchar(50) NOT NULL COMMENT '权限描述',
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='权限表';
立即学习“PHP免费学习笔记(深入)”;
我们可以使用ThinkPHP提供的数据库迁移工具来创建表:php think migrate:run。
接下来,我们需要创建角色和权限的模型。在app/model目录下创建Role.php和Permission.php文件,代码如下:
namespace appmodel;
use thinkModel;
class Role extends Model
{
protected $table = 'role';
}
namespace appmodel;
use thinkModel;
class Permission extends Model
{
protected $table = 'permission';
}
由于一个用户可能拥有多个角色,一个角色也可能对应多个权限,所以我们需要创建一个角色和权限的关联表。在数据库中创建一个role_permission表。
CREATE TABLE role_permission (
id int(11) NOT NULL AUTO_INCREMENT COMMENT '主键',
role_id int(11) NOT NULL COMMENT '角色ID',
permission_id int(11) NOT NULL COMMENT '权限ID',
PRIMARY KEY (id),
KEY role_id (role_id),
KEY permission_id (permission_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='角色-权限关联表';
在模型中定义角色和权限的多对多关系:
namespace appmodel;
use thinkModel;
class Role extends Model
{
protected $table = 'role'; public function permissions() { return $this->belongsToMany( Permission::class, 'role_permission', 'role_id', 'permission_id' ); }
}
namespace appmodel;
use thinkModel;
class Permission extends Model
{
protected $table = 'permission'; public function roles() { return $this->belongsToMany( Role::class, 'role_permission', 'permission_id', 'role_id' ); }
}
在ThinkPHP6中,中间件是处理请求的强大工具,我们可以通过中间件来实现权限控制。创建一个CheckAuth中间件,用于判断用户是否有权限进行当前的操作。在appmiddleware目录下创建CheckAuth.php文件,代码如下:
namespace appmiddleware;
use thinkacadeDb;
use thinkacadeSession;
use thinkacadeConfig;
class CheckAuth
{
public function handle($request, Closure $next) { if (Session::has('user')) { $roles = Db::table('user') ->alias('u') ->leftJoin('role_user ru', 'u.id = ru.user_id') ->leftJoin('role r', 'ru.role_id = r.id') ->where('u.id', '=', Session::get('user')->id) ->field('r.id') ->select(); $permissions = Config::get('permissions'); foreach ($roles as $role) { $rolePermissions = Db::table('role_permission') ->where('role_id', '=', $role->id) ->field('permission_id') ->select(); foreach ($rolePermissions as $rolePermission) { if (in_array($rolePermission->permission_id, $permissions)) { return $next($request); } } } } abort(null, '没有权限'); }
}
该中间件会先查询当前用户所拥有的所有角色,在遍历角色时,查询每个角色所拥有的权限,如果有符合当前请求的权限,就允许继续执行,否则返回403错误。
为了方便管理系统的权限,我们可以使用ThinkPHP提供的Config功能,将所有的权限写入配置文件中。在config目录下创建一个permissions.php文件,代码如下:
return [
1 => 'user.create', 2 => 'user.read', 3 => 'user.update', 4 => 'user.delete',
];
我们可以通过key/value的形式来记录系统所有的权限,key为一个整数,value为一个字符串,表示权限的名称。
最后,我们需要实际应用上述的中间件。打开config目录下的middleware.php文件,添加CheckAuth中间件。
return [
// ... 'check_auth' => appmiddlewareCheckAuth::class,
];
中间件的应用顺序是按照数组的键名从前到后依次执行的,我们可以通过数组下标来调整中间件的执行顺序。
在需要进行权限控制的控制器或方法上,可以使用middleware方法来绑定CheckAuth中间件。
namespace appcontroller;
use thinkacadeView;
class UserController
{
public function create() { $this->middleware('check_auth'); // ... }
}
至此,我们已经完成了使用ThinkPHP6实现用户角色权限管理的所有步骤,您可以根据实际业务需求来扩展和完善上述示例代码。