ThinkPHP项目角色与权限分配

wen PHP项目 6

本文目录导读:

ThinkPHP项目角色与权限分配

  1. 数据库设计
  2. 核心模型类
  3. 鉴权中间件
  4. 权限管理控制器
  5. 路由配置
  6. 模板示例
  7. 权限校验辅助类
  8. 控制器基类
  9. 使用示例

我来详细介绍ThinkPHP项目中角色与权限分配的实现方案,包括数据库设计、核心代码实现和完整示例。

数据库设计

数据表结构

-- 用户表
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(50) NOT NULL COMMENT '用户名',
  `password` varchar(255) NOT NULL COMMENT '密码',
  `email` varchar(100) DEFAULT NULL,
  `status` tinyint(1) DEFAULT '1' COMMENT '状态:1启用,0禁用',
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 角色表
CREATE TABLE `role` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL COMMENT '角色名称',
  `description` varchar(255) DEFAULT NULL COMMENT '角色描述',
  `status` tinyint(1) DEFAULT '1' COMMENT '状态',
  `create_time` datetime DEFAULT NULL,
  `update_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 权限表
CREATE TABLE `permission` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL COMMENT '权限名称',
  `code` varchar(100) NOT NULL COMMENT '权限代码',
  `type` tinyint(1) DEFAULT '1' COMMENT '类型:1菜单,2按钮',
  `parent_id` int(11) DEFAULT '0' COMMENT '父级ID',
  `route` varchar(255) DEFAULT NULL COMMENT '路由地址',
  `sort` int(11) DEFAULT '0' COMMENT '排序',
  `status` tinyint(1) DEFAULT '1',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_code` (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 用户-角色关联表
CREATE TABLE `user_role` (
  `user_id` int(11) NOT NULL,
  `role_id` int(11) NOT NULL,
  PRIMARY KEY (`user_id`,`role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 角色-权限关联表
CREATE TABLE `role_permission` (
  `role_id` int(11) NOT NULL,
  `permission_id` int(11) NOT NULL,
  PRIMARY KEY (`role_id`,`permission_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

核心模型类

User模型

<?php
namespace app\common\model;
use think\Model;
use think\model\concern\SoftDelete;
class User extends Model
{
    use SoftDelete;
    protected $deleteTime = 'delete_time';
    // 关联角色
    public function roles()
    {
        return $this->belongsToMany(Role::class, 'user_role', 'role_id', 'user_id');
    }
    // 获取用户所有权限
    public function getPermissions()
    {
        $roles = $this->roles()->where('status', 1)->select();
        $permissionIds = [];
        foreach ($roles as $role) {
            $permissionIds = array_merge(
                $permissionIds,
                $role->permissions()->column('id')
            );
        }
        return array_unique($permissionIds);
    }
    // 检查是否有指定权限
    public function hasPermission($permissionCode)
    {
        $permissionIds = $this->getPermissions();
        if (empty($permissionIds)) {
            return false;
        }
        return Permission::whereIn('id', $permissionIds)
            ->where('code', $permissionCode)
            ->count() > 0;
    }
    // 检查是否有指定角色
    public function hasRole($roleName)
    {
        return $this->roles()
            ->where('name', $roleName)
            ->where('status', 1)
            ->count() > 0;
    }
}

Role模型

<?php
namespace app\common\model;
use think\Model;
class Role extends Model
{
    // 关联权限
    public function permissions()
    {
        return $this->belongsToMany(Permission::class, 'role_permission', 'permission_id', 'role_id');
    }
    // 关联用户
    public function users()
    {
        return $this->belongsToMany(User::class, 'user_role', 'user_id', 'role_id');
    }
    // 给角色分配权限
    public function assignPermissions(array $permissionIds)
    {
        return $this->permissions()->detach()
            ->then(function () use ($permissionIds) {
                return $this->permissions()->attach($permissionIds);
            });
    }
}

Permission模型

<?php
namespace app\common\model;
use think\Model;
class Permission extends Model
{
    // 获取权限树形结构
    public static function getTree()
    {
        $permissions = self::order('sort', 'asc')->select()->toArray();
        return self::buildTree($permissions);
    }
    // 构建树形结构
    private static function buildTree(array $items, $parentId = 0)
    {
        $tree = [];
        foreach ($items as $item) {
            if ($item['parent_id'] == $parentId) {
                $children = self::buildTree($items, $item['id']);
                if ($children) {
                    $item['children'] = $children;
                }
                $tree[] = $item;
            }
        }
        return $tree;
    }
}

鉴权中间件

权限检查中间件

<?php
namespace app\middleware;
use think\Request;
use think\Response;
use app\common\model\User;
class CheckPermission
{
    public function handle(Request $request, \Closure $next, $permission = null)
    {
        // 获取当前登录用户
        $userId = session('user_id');
        if (!$userId) {
            return redirect('/login');
        }
        $user = User::find($userId);
        if (!$user || $user->status != 1) {
            return redirect('/login');
        }
        // 超级管理员直接通过
        if ($user->hasRole('admin')) {
            return $next($request);
        }
        // 检查权限
        if ($permission && !$user->hasPermission($permission)) {
            if ($request->isAjax()) {
                return json(['code' => 403, 'msg' => '没有权限操作']);
            }
            abort(403, '没有权限访问');
        }
        // 将用户对象绑定到请求
        $request->user = $user;
        return $next($request);
    }
}

权限管理控制器

用户管理控制器

<?php
namespace app\admin\controller;
use think\Request;
use app\common\model\User;
use app\common\model\Role;
use app\common\model\UserRole;
class UserController extends BaseController
{
    // 用户列表
    public function index(Request $request)
    {
        $page = $request->param('page', 1);
        $limit = $request->param('limit', 10);
        $keyword = $request->param('keyword', '');
        $query = User::with(['roles']);
        if ($keyword) {
            $query->where('username', 'like', "%{$keyword}%");
        }
        $list = $query->paginate([
            'page' => $page,
            'list_rows' => $limit
        ]);
        return json([
            'code' => 0,
            'msg' => 'success',
            'data' => $list->items(),
            'count' => $list->total()
        ]);
    }
    // 创建用户
    public function create(Request $request)
    {
        $data = $request->post();
        $validate = new \app\admin\validate\UserValidate();
        if (!$validate->scene('create')->check($data)) {
            return json(['code' => 0, 'msg' => $validate->getError()]);
        }
        $user = new User();
        $user->username = $data['username'];
        $user->password = password_hash($data['password'], PASSWORD_DEFAULT);
        $user->email = $data['email'] ?? '';
        $user->status = $data['status'] ?? 1;
        $user->save();
        // 分配角色
        if (isset($data['role_ids']) && is_array($data['role_ids'])) {
            $user->roles()->attach($data['role_ids']);
        }
        return json(['code' => 1, 'msg' => '创建成功']);
    }
    // 更新用户
    public function update(Request $request, $id)
    {
        $user = User::find($id);
        if (!$user) {
            return json(['code' => 0, 'msg' => '用户不存在']);
        }
        $data = $request->post();
        if (isset($data['password']) && $data['password']) {
            $user->password = password_hash($data['password'], PASSWORD_DEFAULT);
        }
        if (isset($data['email'])) {
            $user->email = $data['email'];
        }
        if (isset($data['status'])) {
            $user->status = $data['status'];
        }
        $user->save();
        // 更新角色
        if (isset($data['role_ids']) && is_array($data['role_ids'])) {
            $user->roles()->detach();
            $user->roles()->attach($data['role_ids']);
        }
        return json(['code' => 1, 'msg' => '更新成功']);
    }
    // 删除用户(软删除)
    public function delete($id)
    {
        $user = User::find($id);
        if (!$user) {
            return json(['code' => 0, 'msg' => '用户不存在']);
        }
        $user->delete();
        return json(['code' => 1, 'msg' => '删除成功']);
    }
    // 分配角色
    public function assignRole(Request $request)
    {
        $userId = $request->post('user_id');
        $roleIds = $request->post('role_ids', []);
        $user = User::find($userId);
        if (!$user) {
            return json(['code' => 0, 'msg' => '用户不存在']);
        }
        $user->roles()->detach();
        $user->roles()->attach($roleIds);
        return json(['code' => 1, 'msg' => '角色分配成功']);
    }
}

角色管理控制器

<?php
namespace app\admin\controller;
use think\Request;
use app\common\model\Role;
use app\common\model\Permission;
class RoleController extends BaseController
{
    // 角色列表
    public function index()
    {
        $roles = Role::with(['permissions'])->select();
        return json(['code' => 0, 'data' => $roles]);
    }
    // 创建角色
    public function create(Request $request)
    {
        $data = $request->post();
        $role = new Role();
        $role->name = $data['name'];
        $role->description = $data['description'] ?? '';
        $role->save();
        // 分配权限
        if (isset($data['permission_ids']) && is_array($data['permission_ids'])) {
            $role->permissions()->attach($data['permission_ids']);
        }
        return json(['code' => 1, 'msg' => '角色创建成功']);
    }
    // 更新角色
    public function update(Request $request, $id)
    {
        $role = Role::find($id);
        if (!$role) {
            return json(['code' => 0, 'msg' => '角色不存在']);
        }
        $data = $request->post();
        if (isset($data['name'])) {
            $role->name = $data['name'];
        }
        if (isset($data['description'])) {
            $role->description = $data['description'];
        }
        $role->save();
        // 更新权限
        if (isset($data['permission_ids'])) {
            $role->permissions()->detach();
            $role->permissions()->attach($data['permission_ids']);
        }
        return json(['code' => 1, 'msg' => '角色更新成功']);
    }
    // 删除角色
    public function delete($id)
    {
        $role = Role::find($id);
        if (!$role) {
            return json(['code' => 0, 'msg' => '角色不存在']);
        }
        // 检查是否有用户使用该角色
        if ($role->users()->count() > 0) {
            return json(['code' => 0, 'msg' => '该角色已被使用,无法删除']);
        }
        $role->delete();
        $role->permissions()->detach();
        return json(['code' => 1, 'msg' => '角色删除成功']);
    }
    // 分配权限
    public function assignPermission(Request $request)
    {
        $roleId = $request->post('role_id');
        $permissionIds = $request->post('permission_ids', []);
        $role = Role::find($roleId);
        if (!$role) {
            return json(['code' => 0, 'msg' => '角色不存在']);
        }
        $role->permissions()->detach();
        $role->permissions()->attach($permissionIds);
        return json(['code' => 1, 'msg' => '权限分配成功']);
    }
}

权限管理控制器

<?php
namespace app\admin\controller;
use think\Request;
use app\common\model\Permission;
use think\facade\Cache;
class PermissionController extends BaseController
{
    // 权限列表(树形)
    public function index()
    {
        $tree = Permission::getTree();
        return json(['code' => 0, 'data' => $tree]);
    }
    // 创建权限
    public function create(Request $request)
    {
        $data = $request->post();
        $permission = new Permission();
        $permission->name = $data['name'];
        $permission->code = $data['code'];
        $permission->type = $data['type'] ?? 1;
        $permission->parent_id = $data['parent_id'] ?? 0;
        $permission->route = $data['route'] ?? '';
        $permission->sort = $data['sort'] ?? 0;
        $permission->save();
        $this->clearCache();
        return json(['code' => 1, 'msg' => '权限创建成功']);
    }
    // 更新权限
    public function update(Request $request, $id)
    {
        $permission = Permission::find($id);
        if (!$permission) {
            return json(['code' => 0, 'msg' => '权限不存在']);
        }
        $data = $request->post();
        if (isset($data['name'])) {
            $permission->name = $data['name'];
        }
        if (isset($data['code'])) {
            $permission->code = $data['code'];
        }
        if (isset($data['route'])) {
            $permission->route = $data['route'];
        }
        $permission->save();
        $this->clearCache();
        return json(['code' => 1, 'msg' => '权限更新成功']);
    }
    // 删除权限
    public function delete($id)
    {
        $permission = Permission::find($id);
        if (!$permission) {
            return json(['code' => 0, 'msg' => '权限不存在']);
        }
        // 检查是否有子权限
        $hasChildren = Permission::where('parent_id', $id)->count();
        if ($hasChildren > 0) {
            return json(['code' => 0, 'msg' => '存在子权限,无法删除']);
        }
        $permission->delete();
        $this->clearCache();
        return json(['code' => 1, 'msg' => '权限删除成功']);
    }
    // 清除缓存
    private function clearCache()
    {
        Cache::delete('all_permissions');
    }
}

路由配置

<?php
// route/app.php
use think\facade\Route;
// 用户管理
Route::group('admin/user', function () {
    Route::get('index', 'admin.User/index');
    Route::post('create', 'admin.User/create');
    Route::put('update/:id', 'admin.User/update');
    Route::delete('delete/:id', 'admin.User/delete');
    Route::post('assign_role', 'admin.User/assignRole');
})->middleware([\app\middleware\CheckPermission::class]);
// 角色管理
Route::group('admin/role', function () {
    Route::get('index', 'admin.Role/index');
    Route::post('create', 'admin.Role/create');
    Route::put('update/:id', 'admin.Role/update');
    Route::delete('delete/:id', 'admin.Role/delete');
    Route::post('assign_permission', 'admin.Role/assignPermission');
})->middleware([\app\middleware\CheckPermission::class]);
// 权限管理
Route::group('admin/permission', function () {
    Route::get('index', 'admin.Permission/index');
    Route::post('create', 'admin.Permission/create');
    Route::put('update/:id', 'admin.Permission/update');
    Route::delete('delete/:id', 'admin.Permission/delete');
})->middleware([\app\middleware\CheckPermission::class]);

模板示例

角色分配界面

<!-- role_assign.html -->
<div class="role-assign-form">
    <form id="roleForm">
        <div class="form-group">
            <label>用户名</label>
            <input type="text" name="username" value="{$user.username}" readonly>
        </div>
        <div class="form-group">
            <label>分配角色</label>
            <div class="checkbox-group">
                {volist name="roles" id="role"}
                <label class="checkbox-inline">
                    <input type="checkbox" name="role_ids[]" 
                           value="{$role.id}"
                           {if in_array($role.id, $userRoleIds)}checked{/if}>
                    {$role.name}
                </label>
                {/volist}
            </div>
        </div>
        <div class="form-group">
            <button type="submit" class="btn btn-primary">保存</button>
        </div>
    </form>
</div>
<script>
$(function() {
    $('#roleForm').on('submit', function(e) {
        e.preventDefault();
        var roleIds = [];
        $('input[name="role_ids[]"]:checked').each(function() {
            roleIds.push($(this).val());
        });
        $.ajax({
            url: '/admin/user/assign_role',
            type: 'POST',
            data: {
                user_id: {$user.id},
                role_ids: roleIds
            },
            success: function(res) {
                if (res.code === 1) {
                    layer.msg('分配成功');
                    location.reload();
                } else {
                    layer.msg(res.msg);
                }
            }
        });
    });
});
</script>

权限树形选择

<!-- permission_tree.html -->
<div class="permission-tree">
    <ul id="permissionTree" class="ztree"></ul>
</div>
<script>
var setting = {
    check: {
        enable: true,
        chkboxType: {"Y": "ps", "N": "ps"}
    },
    data: {
        simpleData: {
            enable: true,
            idKey: "id",
            pIdKey: "parent_id",
            rootPId: 0
        }
    }
};
function initPermissionTree() {
    $.ajax({
        url: '/admin/permission/index',
        type: 'GET',
        success: function(res) {
            if (res.code === 0) {
                var tree = [];
                var permissions = res.data;
                function flattenTree(data, parentId) {
                    $.each(data, function(index, item) {
                        tree.push({
                            id: item.id,
                            parent_id: parentId || 0,
                            name: item.name,
                            open: parentId === 0
                        });
                        if (item.children && item.children.length > 0) {
                            flattenTree(item.children, item.id);
                        }
                    });
                }
                flattenTree(permissions, 0);
                $.fn.zTree.init($("#permissionTree"), setting, tree);
            }
        }
    });
}
// 获取选中的权限ID
function getSelectedPermissionIds() {
    var treeObj = $.fn.zTree.getZTreeObj("permissionTree");
    var nodes = treeObj.getCheckedNodes(true);
    return nodes.map(function(node) {
        return node.id;
    });
}
</script>

权限校验辅助类

<?php
namespace app\common\auth;
use app\common\model\User;
use think\facade\Cache;
use think\facade\Session;
class AuthHelper
{
    // 获取用户权限标识符
    public static function getUserPermissionCodes()
    {
        $userId = Session::get('user_id');
        $cacheKey = 'user_permissions_' . $userId;
        // 尝试从缓存获取
        $permissions = Cache::get($cacheKey);
        if ($permissions) {
            return $permissions;
        }
        // 查询数据库
        $user = User::find($userId);
        if (!$user) {
            return [];
        }
        $roleIds = $user->roles()->column('id');
        $permissions = [];
        if (!empty($roleIds)) {
            $permissionCodes = \app\common\model\RolePermission::alias('rp')
                ->join('permission p', 'p.id = rp.permission_id')
                ->whereIn('rp.role_id', $roleIds)
                ->column('p.code');
            $permissions = array_unique($permissionCodes);
        }
        // 缓存30分钟
        Cache::set($cacheKey, $permissions, 1800);
        return $permissions;
    }
    // 清除用户权限缓存
    public static function clearUserPermission($userId = null)
    {
        if ($userId) {
            Cache::delete('user_permissions_' . $userId);
        } else {
            Cache::delete('user_permissions_' . Session::get('user_id'));
        }
    }
    // 生成权限菜单树
    public static function getMenuTree()
    {
        $permissionCodes = self::getUserPermissionCodes();
        $query = \app\common\model\Permission::where('type', 1)
            ->where('status', 1)
            ->order('sort', 'asc');
        $permissions = $query->select()->toArray();
        return self::buildMenuTree($permissions, 0, $permissionCodes);
    }
    // 构建菜单树
    private static function buildMenuTree($permissions, $parentId, $userPermissions)
    {
        $tree = [];
        foreach ($permissions as $permission) {
            if ($permission['parent_id'] == $parentId) {
                // 检查是否有权限
                if (!in_array($permission['code'], $userPermissions)) {
                    continue;
                }
                $children = self::buildMenuTree($permissions, $permission['id'], $userPermissions);
                if ($children || $permission['route']) {
                    $tree[] = [
                        'id' => $permission['id'],
                        'name' => $permission['name'],
                        'route' => $permission['route'],
                        'children' => $children
                    ];
                }
            }
        }
        return $tree;
    }
}

控制器基类

<?php
namespace app\admin\controller;
use app\common\auth\AuthHelper;
use think\Controller;
use think\facade\Session;
class BaseController extends Controller
{
    protected $user;
    protected function initialize()
    {
        parent::initialize();
        // 用户登录检查
        if (!Session::has('user_id')) {
            $this->redirect('/login');
        }
        // 获取当前用户信息
        $this->user = \app\common\model\User::find(Session::get('user_id'));
        // 判断是否超级管理员
        $isAdmin = $this->user->hasRole('admin');
        $this->assign('isAdmin', $isAdmin);
        // 获取并分配菜单
        $menus = $isAdmin ? $this->getAllMenus() : AuthHelper::getMenuTree();
        $this->assign('menus', $menus);
        // 获取用户信息
        $this->assign('user', $this->user);
    }
    // 获取所有菜单(管理员)
    private function getAllMenus()
    {
        return \app\common\model\Permission::where('type', 1)
            ->where('status', 1)
            ->order('sort', 'asc')
            ->select()
            ->toArray();
    }
}

使用示例

在控制器中使用权限检查

<?php
namespace app\admin\controller;
class OrderController extends BaseController
{
    // 订单列表(需要权限)
    public function index()
    {
        // 自定义权限检查
        if (!$this->user->hasPermission('order_view')) {
            return json(['code' => 403, 'msg' => '没有订单查看权限']);
        }
        // 处理业务逻辑...
        return $this->fetch();
    }
    // 删除订单(需要权限)
    public function delete($id)
    {
        if (!$this->user->hasPermission('order_delete')) {
            return json(['code' => 403, 'msg' => '没有订单删除权限']);
        }
        // 处理删除逻辑...
        return json(['code' => 1, 'msg' => '删除成功']);
    }
}

初始化权限数据

<?php
// think 命令行工具创建初始化脚本
namespace app\common\command;
use think\console\Command;
use think\console\Input;
use think\console\Output;
use think\Db;
class Init extends Command
{
    protected function configure()
    {
        $this->setName('init')
            ->setDescription('初始化权限数据');
    }
    protected function execute(Input $input, Output $output)
    {
        // 创建超级管理员角色
        $adminRole = new \app\common\model\Role();
        $adminRole->name = 'admin';
        $adminRole->description = '超级管理员';
        $adminRole->id = 1;
        $adminRole->save();
        // 创建基础权限
        $permissions = [
            ['name' => '用户管理', 'code' => 'user_manage', 'type' => 1, 'parent_id' => 0],
            ['name' => '用户列表', 'code' => 'user_list', 'type' => 2, 'parent_id' => 1],
            ['name' => '用户添加', 'code' => 'user_create', 'type' => 2, 'parent_id' => 1],
            ['name' => '用户编辑', 'code' => 'user_edit', 'type' => 2, 'parent_id' => 1],
            ['name' => '用户删除', 'code' => 'user_delete', 'type' => 2, 'parent_id' => 1],
            ['name' => '角色管理', 'code' => 'role_manage', 'type' => 1, 'parent_id' => 0],
            ['name' => '角色列表', 'code' => 'role_list', 'type' => 2, 'parent_id' => 6],
            ['name' => '权限管理', 'code' => 'permission_manage', 'type' => 1, 'parent_id' => 0],
        ];
        $permissionIds = [];
        foreach ($permissions as $item) {
            $permission = new \app\common\model\Permission();
            $permission->save($item);
            $permissionIds[] = $permission->id;
        }
        // 给管理员分配所有权限
        $adminRole->permissions()->attach($permissionIds);
        // 创建管理员用户
        $admin = new \app\common\model\User();
        $admin->username = 'admin';
        $admin->password = password_hash('admin123', PASSWORD_DEFAULT);
        $admin->save();
        // 给管理员分配角色
        $admin->roles()->attach([1]);
        $output->writeln('初始化完成');
    }
}

这个完整的权限管理方案包含了:

  1. 数据库设计:用户、角色、权限表及关联表
  2. 模型层:核心模型的关联关系
  3. 中间件:权限校验
  4. 控制器:CRUD操作及权限分配
  5. 辅助类:权限缓存、菜单生成等
  6. 使用示例:控制器级权限控制、模板渲染等

你可以根据项目实际需求进行调整和扩展。

抱歉,评论功能暂时关闭!