From 80255727135250fe89b215bef1085071ee76cc54 Mon Sep 17 00:00:00 2001 From: molong Date: Tue, 3 Dec 2019 21:34:56 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=8F=E6=9B=B4=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/controller/Admin.php | 116 ++++++++++++++++++++++++++++++--- app/controller/admin/Index.php | 59 ++++++++--------- app/http/middleware/Admin.php | 31 ++++++--- app/model/Menu.php | 19 ++---- composer.json | 47 ++++++++----- config/app.php | 52 +++++++-------- 6 files changed, 219 insertions(+), 105 deletions(-) diff --git a/app/controller/Admin.php b/app/controller/Admin.php index 97724ace..3e2fd9d6 100644 --- a/app/controller/Admin.php +++ b/app/controller/Admin.php @@ -9,7 +9,9 @@ namespace app\controller; use app\BaseController; +use sent\auth\Auth; use think\facade\Cache; +use think\facade\Config; /** * @title 后端公共模块 @@ -18,13 +20,12 @@ class Admin extends BaseController { protected $middleware = [ '\app\http\middleware\Validate', - '\app\http\middleware\AdminAuth' => ['except' => ['login']], - '\app\http\middleware\Admin' + '\app\http\middleware\Admin', ]; protected $data = ['data' => [], 'code' => 0, 'msg' => '']; - protected function initialize(){ + protected function initialize() { $config = Cache::get('system_config'); if (!$config) { $config = (new \app\model\Config())->lists(); @@ -33,17 +34,114 @@ class Admin extends BaseController { $this->data['config'] = $config; } - protected function success($msg, $url = ''){ + protected function success($msg, $url = '') { $this->data['code'] = 0; - $this->data['msg'] = $msg; - $this->data['url'] = $url ? $url->__toString() : ''; + $this->data['msg'] = $msg; + $this->data['url'] = $url ? $url->__toString() : ''; return $this->data; } - protected function error($msg, $url = ''){ + protected function error($msg, $url = '') { $this->data['code'] = 1; - $this->data['msg'] = $msg; - $this->data['url'] = $url ? $url->__toString() : ''; + $this->data['msg'] = $msg; + $this->data['url'] = $url ? $url->__toString() : ''; return $this->data; } + + /** + * 授权配置 + * @param [type] $request [description] + * @return [type] [description] + */ + protected function auth($request) { + // 是否是超级管理员 + define('IS_ROOT', is_administrator()); + if (!IS_ROOT && Config::get('admin_allow_ip')) { + // 检查IP地址访问 + if (!in_array(get_client_ip(), explode(',', Config::get('admin_allow_ip')))) { + $this->error('403:禁止访问'); + } + } + + // 检测系统权限 + if (!IS_ROOT) { + $access = $this->accessControl(); + if (false === $access) { + $this->error('403:禁止访问'); + } elseif (null === $access) { + $dynamic = $this->checkDynamic(); //检测分类栏目有关的各项动态权限 + if ($dynamic === null) { + //检测访问权限 + if (!$this->checkRule($this->url_path, array('in', '1,2'))) { + $this->error('未授权访问!'); + } else { + // 检测分类及内容有关的各项动态权限 + $dynamic = $this->checkDynamic(); + if (false === $dynamic) { + $this->error('未授权访问!'); + } + } + } elseif ($dynamic === false) { + $this->error('未授权访问!'); + } + } + } + } + + /** + * 权限检测 + * @param string $rule 检测的规则 + * @param string $mode check模式 + * @return boolean + * @author 朱亚杰 + */ + final protected function checkRule($rule, $type = AuthRule::rule_url, $mode = 'url') { + static $Auth = null; + if (!$Auth) { + $Auth = new Auth(); + } + if (!$Auth->check($rule, session('user_auth.uid'), $type, $mode)) { + return false; + } + return true; + } + + /** + * 检测是否是需要动态判断的权限 + * @return boolean|null + * 返回true则表示当前访问有权限 + * 返回false则表示当前访问无权限 + * 返回null,则表示权限不明 + * + * @author 朱亚杰 + */ + protected function checkDynamic() { + if (IS_ROOT) { + return true; //管理员允许访问任何页面 + } + return null; //不明,需checkRule + } + + /** + * action访问控制,在 **登陆成功** 后执行的第一项权限检测任务 + * + * @return boolean|null 返回值必须使用 `===` 进行判断 + * + * 返回 **false**, 不允许任何人访问(超管除外) + * 返回 **true**, 允许任何管理员访问,无需执行节点权限检测 + * 返回 **null**, 需要继续执行节点权限检测决定是否允许访问 + * @author 朱亚杰 + */ + final protected function accessControl() { + $allow = Config::get('allow_visit'); + $deny = Config::get('deny_visit'); + $check = strtolower($this->request->controller() . '/' . $this->request->action()); + if (!empty($deny) && in_array_case($check, $deny)) { + return false; //非超管禁止访问deny中的方法 + } + if (!empty($allow) && in_array_case($check, $allow)) { + return true; + } + return null; //需要检测节点权限 + } } diff --git a/app/controller/admin/Index.php b/app/controller/admin/Index.php index f9b93097..1037d2a7 100644 --- a/app/controller/admin/Index.php +++ b/app/controller/admin/Index.php @@ -9,32 +9,32 @@ namespace app\controller\admin; use app\controller\Admin; -use think\facade\Session; use app\model\Menu; +use think\facade\Session; /** * @title 后端公共模块 */ -class Index extends Admin{ +class Index extends Admin { /** * @title 系统首页 */ - public function index(Menu $menu){ - $this->data['data'] = array('menu' => $menu->getMenu($this->request)); + public function index(Menu $menu) { + $this->data['data'] = array('menu' => $menu->getAuthMenuList($this->request)); return $this->data; } - + /** * @title 系统首页 */ - public function dashboard(){ + public function dashboard() { } /** * @title 更新缓存 */ - public function clear(){ + public function clear() { if ($this->request->isAjax()) { $root = app()->getRootPath() . 'runtime/'; $this->delDirAndFile($root); @@ -42,39 +42,40 @@ class Index extends Admin{ } } - /** 递归删除文件 - * @param $dirName - * @param bool $subdir - */ - protected function delDirAndFile($dirName) - { - $list = glob($dirName . '*'); - foreach ($list as $file) { - if (is_dir($file)) - $this->delDirAndFile($file . '/'); - else - @unlink($file); - } - @rmdir($dirName); - } + /** 递归删除文件 + * @param $dirName + * @param bool $subdir + */ + protected function delDirAndFile($dirName) { + $list = glob($dirName . '*'); + foreach ($list as $file) { + if (is_dir($file)) { + $this->delDirAndFile($file . '/'); + } else { + @unlink($file); + } + + } + @rmdir($dirName); + } /** * @title 后台登录 */ - public function login(\app\model\Member $member){ + public function login(\app\model\Member $member) { if ($this->request->isAjax()) { $username = $this->request->param('username', ''); $password = $this->request->param('password', ''); - $user = $member->login($username, $password); + $user = $member->login($username, $password); if ($user) { Session::set('user', $user); $this->data['url'] = "/admin/index/index.html"; $this->data['msg'] = "登录成功!"; - }else{ + } else { Session::set('user', null); $this->data['code'] = 1; - $this->data['msg'] = "登录失败!"; + $this->data['msg'] = "登录失败!"; } - + return $this->data; } } @@ -82,10 +83,10 @@ class Index extends Admin{ /** * @title 后台登出 */ - public function logout(){ + public function logout() { Session::set('user', null); $this->data['code'] = 0; - $this->data['msg'] = "成功退出!"; + $this->data['msg'] = "成功退出!"; return $this->data; } } diff --git a/app/http/middleware/Admin.php b/app/http/middleware/Admin.php index daf58705..3ab65716 100644 --- a/app/http/middleware/Admin.php +++ b/app/http/middleware/Admin.php @@ -8,6 +8,7 @@ // +---------------------------------------------------------------------- namespace app\http\middleware; +use think\facade\Session; use think\facade\View; /** @@ -15,13 +16,23 @@ use think\facade\View; */ class Admin { - protected $data = []; + protected $data = []; + protected $outAuth = ['admin/index/login', 'admin/index/logout', 'admin/index/verify']; public function handle($request, \Closure $next) { + $user = Session::get('user'); + $request->url = str_replace(".", "/", strtolower($request->controller())) . '/' . $request->action(); + if (!Session::has('user') && !$user['uid'] && !in_array($request->url, $this->outAuth)) { + return redirect('admin/index/login'); + } + $request->isAdmin = 1; + $request->user = $user; + $request->pageConfig = array( - 'list_rows' => $request->param('limit', 20), - 'page' => $request->param('page', 1) + 'list_rows' => $request->param('limit', 20), + 'page' => $request->param('page', 1), ); + $response = $next($request); if (is_array($response->getData())) { @@ -36,9 +47,9 @@ class Admin { } return json($this->data); } else { - if(\is_string($this->data) && $this->data != ''){ + if (\is_string($this->data) && $this->data != '') { return $response; - }else{ + } else { return $response->data($this->fetch()); } } @@ -51,11 +62,11 @@ class Admin { // 使用内置PHP模板引擎渲染模板输出 $config = array( 'tpl_replace_string' => array( - '__static__' => '/static', - '__img__' => '/static/admin/images', - '__css__' => '/static/admin/css', - '__js__' => '/static/admin/js', - '__public__' => '/static/admin', + '__static__' => '/static', + '__img__' => '/static/admin/images', + '__css__' => '/static/admin/css', + '__js__' => '/static/admin/js', + '__public__' => '/static/admin', ), ); diff --git a/app/model/Menu.php b/app/model/Menu.php index 5528c283..3e8f8b52 100644 --- a/app/model/Menu.php +++ b/app/model/Menu.php @@ -9,28 +9,27 @@ namespace app\model; +use think\facade\Cache; use think\Model; use think\Request; -use think\facade\Cache; /** * @title: ˵ģ */ class Menu extends Model { - /** * @title ʾ˵ */ - public function getMenu(Request $request) { - $list = []; + public function getAuthMenuList(Request $request) { + $list = []; $current_controller = '/' . str_replace('.', '/', strtolower($request->controller())); - $current_url = $current_controller . '/' . strtolower($request->action()); + $current_url = $request->url; $menu = Cache::get('menu'); if (!$menu) { - $res = (new \app\model\Menu())->where('is_menu', 1)->order('sort asc, id asc')->select(); + $res = self::where('is_menu', 1)->order('sort asc, id asc')->select()->toArray(); foreach ($res as $key => $item) { - $menu[$item['id']] = $item->toArray(); + $menu[$item['id']] = $item; } Cache::set('menu', $menu); } @@ -43,10 +42,4 @@ class Menu extends Model { $menuList = list_to_tree($list); return $menuList; } - - public function getAuthMenuList(){ - $list = $this->select(); - $data = list_to_tree($list->toArray(), 'id', 'pid'); - return $data; - } } \ No newline at end of file diff --git a/composer.json b/composer.json index bc0a0a98..942805a6 100644 --- a/composer.json +++ b/composer.json @@ -10,41 +10,52 @@ "homepage": "http://thinkphp.cn/", "license": "Apache-2.0", "authors": [ - { - "name": "liu21st", - "email": "liu21st@gmail.com" - } - ], - "require": { + { + "name": "liu21st", + "email": "liu21st@gmail.com" + }], + "require": + { "php": ">=7.1.0", - "topthink/framework": "6.0.*-dev", - "topthink/think-orm": "2.0.*-dev", + "topthink/framework": "^6.0.0", + "topthink/think-orm": "^2.0.28", "topthink/think-view": "^1.0", - "xaboy/form-builder": "~2.0", - "overtrue/wechat": "~4.0" + "overtrue/wechat": "~4.0", + "xin/helper": "^1.0", + "sent/think-auth": "^1.1", + "sent/think-jwt": "^1.0.0", + "sent/tree": "^1.0.0" }, - "require-dev": { + "require-dev": + { "symfony/var-dumper": "^4.2" }, - "autoload": { - "psr-4": { + "autoload": + { + "psr-4": + { "app\\": "app" }, - "psr-0": { + "psr-0": + { "": "extend/" } }, - "config": { + "config": + { "preferred-install": "dist" }, - "scripts": { + "scripts": + { "post-autoload-dump": [ "@php think service:discover", "@php think vendor:publish" ] }, - "repositories": { - "packagist": { + "repositories": + { + "packagist": + { "type": "composer", "url": "https://packagist.phpcomposer.com" } diff --git a/config/app.php b/config/app.php index c0059c3b..d1e34ecb 100644 --- a/config/app.php +++ b/config/app.php @@ -6,32 +6,32 @@ use think\facade\Env; return [ - // 应用地址 - 'app_host' => Env::get('app.host', ''), - // 应用的命名空间 - 'app_namespace' => '', - // 是否启用路由 - 'with_route' => true, - // 是否启用事件 - 'with_event' => true, - // 自动多应用模式 - 'auto_multi_app' => false, - // 应用映射(自动多应用模式有效) - 'app_map' => [], - // 域名绑定(自动多应用模式有效) - 'domain_bind' => [], - // 禁止URL访问的应用列表(自动多应用模式有效) - 'deny_app_list' => [], - // 默认应用 - 'default_app' => 'index', - // 默认时区 - 'default_timezone' => 'Asia/Shanghai', + // 应用地址 + 'app_host' => Env::get('app.host', ''), + // 应用的命名空间 + 'app_namespace' => '', + // 是否启用路由 + 'with_route' => true, + // 是否启用事件 + 'with_event' => true, + // 自动多应用模式 + 'auto_multi_app' => false, + // 应用映射(自动多应用模式有效) + 'app_map' => [], + // 域名绑定(自动多应用模式有效) + 'domain_bind' => [], + // 禁止URL访问的应用列表(自动多应用模式有效) + 'deny_app_list' => [], + // 默认应用 + 'default_app' => 'index', + // 默认时区 + 'default_timezone' => 'Asia/Shanghai', - // 异常页面的模板文件 - 'exception_tmpl' => app()->getThinkPath() . 'tpl/think_exception.tpl', + // 异常页面的模板文件 + 'exception_tmpl' => app()->getThinkPath() . 'tpl/think_exception.tpl', - // 错误显示信息,非调试模式有效 - 'error_message' => '页面错误!请稍后再试~', - // 显示错误信息 - 'show_error_msg' => false, + // 错误显示信息,非调试模式有效 + 'error_message' => '页面错误!请稍后再试~', + // 显示错误信息 + 'show_error_msg' => true, ];