# 进阶篇三 实战开发之权限控制 [TOC] ## 权限控制的作用 >[info] 在项目中,特别是后台管理的项目中,权限控制非常重要,有些页面要求不限制访问,有些页面要求登陆后才能访问,还有些重要页面,必须是指定的角色才能访问.在MVC项目中,我们可以通过控制每一个控制器的节点的权限达到我们的需求. ## 巧用控制器基类 达到权限控制的目的 首先 咱们先点有一套 验证登录 设置登录 设置退出的方法, 注意这个方法都是放在 base/controller中 ### 全局登录函数组 详细使用方法参照 https://www.kancloud.cn/mikkle/thinkphp5_study/349347 * 检查全局登录 ~~~ /** * 检测是否登录 * Power by Mikkle * QQ:776329498 * @return bool */ public function checkLoginGlobal() { $check_success = false; switch ($this->loginType) { case 1; case "session"; $this->uuid = Session::get('uuid', 'Global'); $this->member_info = Session::get('member_info', 'Global'); if ($this->uuid && $this->member_info) { $check_success = true; } break; case 2; case "cache"; $session_id_check = Cookie::get("session_id"); $this->uuid = Cache::get("uuid_{$session_id_check}"); $this->member_info = Cache::get("member_info_{$session_id_check}"); if ($this->uuid && $this->member_info) { $check_success = true; } //刷新 缓存有效期 Cache::set("uuid_{$session_id_check}", $this->uuid); Cache::set("member_info_{$session_id_check}", $this->member_info); break; case 3: case "redis": //这部分不方便共享 不好意思 break; } return $check_success; } ~~~ * 设置全局登录 ~~~ /** * 设置全局登录 * #User: Mikkle * #Email:776329498@qq.com * #Date: */ public function setLoginGlobal($member_info = [], $login_code = 0) { $set_success = false ; if ($member_info) { switch ($this->loginType) { case 1: case "session": Session::set('member_info', $member_info, 'Global'); Session::set('uuid', $member_info['uuid'], 'Global'); if ((Session::has("uuid", "Global"))) { $set_success = true; } break; case 2: case "cache": $session_id = $this->create_uuid("SN"); Cookie::set("session_id", $session_id); Cache::set("member_info_$session_id", $member_info); Cache::set("uuid_$session_id", $member_info['uuid']); $session_id_check = Cookie::get("session_id"); if ((Cache::get("uuid_{$session_id_check}"))) { $set_success = true; } break; case 3:case "redis": //这部分不方便共享 不好意思 break; } } if (!$set_success) return false; //保存登录记录 $this->saveLoginInfo($member_info['uuid'],$login_code); return true; } ~~~ * 设置全局退出 ~~~ /** * 全局退出 * Power by Mikkle * QQ:776329498 * @return bool */ protected function logoutGlobal(){ switch ($this->loginType) { case 1: case "session": Session::delete('uuid', 'Global'); Session::delete('member_info', 'Global'); break; case 2: case "cache": $session_id_check = Cookie::get("session_id"); Cache::rm("uuid_{$session_id_check}"); Cache::rm("member_info_{$session_id_check}"); Cookie::delete("session_id"); break; case 3:case "redis": //这部分不方便共享 不好意思 break; } $this->member_info = null; $this->uuid = null; return true; } ~~~ ### 在模块控制器基类的构造函数检验权限 比如说现在的wechat 模块 ~~~ <?php /** * Created by PhpStorm. * Power by Mikkle * QQ:776329498 * Date: 2017/4/17 * Time: 9:33 */ namespace app\wechat\controller; class Base extends \app\base\controller\Base { protected $isLogin = false; //判断是否登陆 protected $uuid; //登陆后的UUID protected $config_list=[]; /** * 检查登陆信息 * Power by Mikkle * QQ:776329498 */ public function _initialize() { if ($this->checkLoginGlobal()) { $this->isLogin = true; } } } ~~~ 这样继承这个基类的方法 都可以通过 $this->uuid 是否存在 来判断是否登录 ~~~ public function test(){ //检验用户是否登录 if (!$this->uuid){ return self::showReturnCodeWithOutData(1004); } //使用用户信息 dump($this->member_info); } ~~~ ### 重要节点的权限判断 接下来 我们再建立一个Auth权限基类 看源码 ~~~ <?php /** * Created by PhpStorm. * Power by Mikkle * QQ:776329498 * Date: 2017/4/17 * Time: 14:47 */ namespace app\wechat\controller; use app\base\model\PersonnelNode; use app\base\model\PersonnelRoleNodeAccess; use think\Session; abstract class Auth extends Base { //權限跳过检验的节点 protected $index_array=[ 'Index'=>[ 'index'=>true, 'login'=>true, 'getmenujson'=>true, ], ]; protected $log_string; protected $member_info; public function _initialize() { parent::_initialize(); // TODO: Change the autogenerated stub //检测是否登陆 if(!$this->isLogin) { $this->redirect('index/login'); } //检测登陆权限 $auth =$this->checkNodeAuth(); //dump($auth); if($auth!=true || $auth==false || is_string($auth)){ // dump($this->log_string); $this->error($this->log_string,"index/index"); } $this->member_info = Session::get('member_info','Global'); } /** * 获取当前访问节点 * Power: Mikkle * Email:776329498@qq.com * @return bool */ protected function checkNodeAuth() { if ($this->checkIsAdmin()) { return true; } else { $request = $this->request; if ($this->checkIsIndex($request->controller(), $request->action())) { return true; } //检测权限// 当前模块名 $node = new PersonnelNode(); //跳过登录系列的检测以及主页权限 $node_info = $node->getNodeInfo($request->module(), $request->controller(), $request->action()); if (empty($node_info)) { $this->log_string='此页面访问权限未开放,请联系管理员'; return false; } if ($node_info['auth_grade'] > 0) { return $this->checkUserNodeAuthByNodeGuId($node_info['guid']); } return true; } } /** * 检测节点是否可以默认登录 * Power: Mikkle * Email:776329498@qq.com * @param $controller * @param $action * @return bool */ protected function checkIsIndex($controller,$action) { return isset($this->index_array[$controller][$action])? true : false ; } /** * 判断用户是否有节点权限 * Power: Mikkle * Email:776329498@qq.com * @param $Guid * @return bool */ protected function checkUserNodeAuthByNodeGuId($Guid) { $member = $this->member_info; $node_list =[]; if (Session::has("role_node_list_{$Guid}")){ $node_list=Session::has("role_node_list_{$Guid}"); }else{ $model = new PersonnelRoleNodeAccess(); $node_list = $model->getRoleMenuList($member['role_id'],1); } if (!in_array($Guid, $node_list)) { $this->log_string="你没有权限,请联系系统管理员"; return false; }else{ return true; } } /** * 检测是否是管理员 * Power: Mikkle * Email:776329498@qq.com * @return bool */ protected function checkIsAdmin() { if (Session::has('is_admin')) { return true; } else { return false; } } } ~~~ OK 剩余的就是把授权节点的信息写入权限表[PersonnelRoleNodeAccess]中即可! ### 控制器继承Auth类 即可验证权限 剩余要做的 就是需要验证登录的控制器继承Auth ~~~ <?php /** * Created by PhpStorm. * User: Administrator * Date: 2017/5/23 * Time: 13:02 */ namespace app\wechat\controller; class Project extends Auth { } ~~~ 感谢大家关注 交流请加QQ群 321449759 ![](https://box.kancloud.cn/3499008a08e64306c68873288092a057_286x340.png)