企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## 权限管理主要由三部分组成: 1. 角色 2. 权限节点 3. 用户 ### 对应关系如下: **权限节点绑定到角色上面,角色再与用户绑定。** ***** ### **权限的验证** #### 操作菜单如何展示? 1. 首先用户登陆 2. 根据用户id查到他的角色 3. 再根据角色查到他可用的操作节点 4. 然后对于操作节点自身的分组id进行分组 5. 最后将这些分组通过json传递到前端或者后端进行拼接后展示给用户。 6. 这样就实现了,如果用户没有操作权限的话就不会展示用户操作菜单。 ***** ### 操作数据的验证如何进行? **每一次用户点击操作菜单的时候,对于整个操作详情界面往往都有增删改查4种操作。 对于每一种操作,都按照上面的角色用户对应关系进行查询。** 1. 拿到用户的所的权限节点 2. 对于数据操作,首先判断用户权限节点中是否存在这些操作。 3. 有,则进行操作。 4. 没有,则提示用户没有权限。 ### **在thinkphp5中如何实现权限的验证呢**?** 我用到了中间件来验证用户登陆情况,然后在后台模块的父控制器中,我根据用户的登陆情况对用户的可操作节点进行了判断。 中间件代码如下,更多的请看代码库中的代码:[https://gitee.com/leihenshang/gossip_blog](https://gitee.com/leihenshang/gossip_blog) ``` <?php namespace app\\http\\middleware; use app\\common\\controller\\BackendBase; class Check { public function handle($request, \\Closure $next) { $backendBaseObject = new BackendBase(); $backendBaseObject\->checkLoginStatus(); return $next($request); } } ``` 权限验证代码: ``` <?php namespace app\\common\\controller; use app\\common\\model\\Permission; use app\\common\\model\\RolePermissionRelation; use app\\common\\model\\UserRoleRelation; use app\\common\\model\\User; use think\\Controller; use think\\facade\\Cookie; use think\\facade\\Request; use think\\facade\\Session; class BackendBase extends Controller { //超级管理员名称 protected $superUserName = 'tangq'; //指定中间件 protected $middleware = \['Check'\]; //存储用户信息和用户权限节点在当前类的子类中共享 protected $userinfo = null; public static $userPermission = null; //设置是否进行权限验证,true验证,false不验证 public function checkPermission() { return false; } /\*\* \* 获取用户信息 \* @param int $type 1为session 2 为Cookie \* @return void \*/ public function getUserInfo($type = 1) { if ($type === 1) { $userinfo = Session::get('userinfo'); if (empty($userinfo) || $userinfo\['expire\_time'\] < time()) { $userinfo = false; } return $userinfo; } else { $userinfo = Cookie::get('userinfo'); $userinfo = json\_decode($userinfo, true); if (empty($userinfo) || $userinfo\['expire\_time'\] < time()) { $userinfo = false; } return $userinfo; } } /\*\* \* 检查用户登陆状态 \*/ public function checkLoginStatus() { //获取用户登陆信息 $this\->userinfo = $this\->getUserInfo(); if($this\->userinfo === false){ // return returnData(false,'获取用户信息失败'); $this\->error('重新登陆','index/user/index','',1); } //检查用户是否在其他地方登录 if (Request::controller() == 'MyCenter') { if (false === User::checkOnlyLogin($this\->userinfo)) { User::clearUserinfo(); $this\->error('您可能在其他地方登录,请重新登录尝试', 'index/user/index', '', 1); } } if (true === $this\->checkPermission()) { //后台页面权限控制 if (Request::controller() == 'MyCenter') { if (!$this\->userinfo) { $this\->error('用户信息错误,请重新登陆', 'index/user/index', '', 1); } //根据用户信息获取当前用户全部可访问节点 $userPermission = $this\->getPermissionNode($this\->userinfo); //获取请求路径信息 $pathInfo = $this\->getUserRequestPath($userPermission); //判断权限验证结果 if ($pathInfo === false) { $this\->error('没有访问权限', 'index/index/index', '', 1); } } else { //定义json返回结构 $data = \['success' => false, 'msg' => '没有访问权限', 'data' => \[\], 'status' => 200\]; //没有找到用户信息的情况 if (!$this\->userinfo) { //指定json header头 header('Content-type:text/json'); echo json\_encode($data); die; } //判断节点权限 $userPermission = $this\->getPermissionNode($this\->userinfo); //获取请求路径信息 $pathInfo = $this\->getUserRequestPath($userPermission); //判断权限验证结果 if ($pathInfo === false) { //指定json header头 header('Content-type:text/json'); echo json\_encode($data); die; } } } else { $this\->userinfo\->username = 'tangq'; $userPermission = $this\->getPermissionNode($this\->userinfo); } //存储用户可访问节点 self::$userPermission = $userPermission; // $this->userPermission = $userPermission; //为模板写入用户信息 $this\->assign('userinfo', $this\->userinfo); //为模板写入后台管理菜单列表 $this\->assign('menuList', $this\->getMenu($this\->userinfo)); } /\*\* \* 获取用户真实请求路径,返回用户请求的路径的数组 \* @param array $userPermission 用户节点信息一维数组 \* @return void \*/ public function getUserRequestPath($userPermission = \[\]) { if (empty($userPermission)) { return false; } $pathInfo = \[Request::path()\]; $routeInfo = Request::routeInfo(); if (!empty($routeInfo)) { $pathInfo\[\] = $routeInfo\['route'\]; } //判断节点权限 $res = false; foreach ($pathInfo as $pathValue) { if (in\_array($pathValue, $userPermission)) { $res = true; break; } } //返回结果 return $res; } /\*\* \* 根据用户信息获取权限节点 \* \* @param object $userId \* @param int $nodeType 节点类型 0 全部,1分组,2页面,3功能性节点 \* @return void \*/ public function getPermissionNode($userInfo, $nodeType = 0) { if (!$userInfo) { return \[\]; } //超级用户返回所有权限节点 if ($userInfo\->username === $this\->superUserName) { $userPermissionUrl = Permission::column('node\_url'); return $userPermissionUrl; } //根据用户id获取用户属于哪个角色 $userRoleId = UserRoleRelation::where('user\_id', $userInfo\->id)->column('role\_id'); if (!$userRoleId) { return \[\]; } //获取用户所属角色的权限节点id $userPermissionId = RolePermissionRelation::where('role\_id', 'in', $userRoleId)->where('is\_deleted', 0)->column('permission\_id'); //获取权限节点url $userPermissionUrl = Permission::where('id', 'in', $userPermissionId)->where('is\_deleted', 0)->column('node\_url'); if ($nodeType != 0) { $userPermissionUrl\->where('type', $nodeType); } return $userPermissionUrl; } /\*\* \* 获取后台管理菜单列表 \* \* @param string $userinfo 用户信息 \* \* @return array \*/ public function getMenu($userinfo) { $arr = \[\]; if (!empty($userinfo)) { if ($userinfo\->username == $this\->superUserName) { //获取用户用户的菜单列表 $resMenu = Permission::field('id,name,node\_url,p\_id,is\_expand')->where('type', 'in', \[0, 1\])->select()->toArray(); } else { //获取用户属于哪个角色 $userRole = UserRoleRelation::where('user\_id', $userinfo\->id)->column('role\_id'); if (!$userRole) { $this\->error('没有指定用户的角色', '', '', 1); } //获取用户所属角色的权限节点 $userPermission = RolePermissionRelation::where('role\_id', 'in', $userRole)->where('is\_deleted', 0)->column('permission\_id'); //获取权限节点 $resMenu = Permission::field('id,name,node\_url,p\_id,is\_expand')->where('type', 'in', \[0, 1\])->where('is\_deleted', 0)->where('id', 'in', $userPermission)->select()->toArray(); } } else { return \[\]; } //处理url以及设置子节点 foreach ($resMenu as $value) { $value\['node\_url'\] = $value\['node\_url'\] == '#' ? 'javascript:;' : $value\['node\_url'\]; //处理url if ($value\['node\_url'\] != 'javascript:;') { $value\['node\_url'\] = mb\_substr($value\['node\_url'\], 0, 1) == '/' ? $value\['node\_url'\] : '/' . $value\['node\_url'\]; } $value\['child'\] = \[\]; $arr\[$value\['id'\]\] = $value; } //生成父子节点 foreach ($resMenu as $key => $value) { if (isset($arr\[$value\['p\_id'\]\])) { $arr\[$value\['p\_id'\]\]\['child'\]\[\] = $value; unset($arr\[$value\['id'\]\]); } } return $arr; } } ```