diff --git a/.gitignore b/.gitignore index d465120..8e098ed 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ /.idea /.vscode -/vendor *.log .env \ No newline at end of file diff --git a/extend/.gitignore b/extend/.gitignore deleted file mode 100644 index c96a04f..0000000 --- a/extend/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -* -!.gitignore \ No newline at end of file diff --git a/vendor/taoser/think-auth/LICENSE b/vendor/taoser/think-auth/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/vendor/taoser/think-auth/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/taoser/think-auth/README.md b/vendor/taoser/think-auth/README.md new file mode 100644 index 0000000..c4701b6 --- /dev/null +++ b/vendor/taoser/think-auth/README.md @@ -0,0 +1,254 @@ +# thinkphp-auth + +ThinkPHP6权限Auth扩展 + +## 安装 + +~~~php +//thinkphp6.0 +composer require taoser/think-auth +~~~ + +## 配置 +~~~php +// 安装之后会在config目录里生成auth.php配置文件,无需数据表前缀 +return[ + 'auth_on' => true, // 认证开关 + 'auth_type' => 1, // 认证方式,1为实时认证;2为登录认证。 + 'auth_group' => 'auth_group', // 用户组数据表名 + 'auth_group_access' => 'auth_group_access', // 用户-用户组关系表 + 'auth_rule' => 'auth_rule', // 权限规则表 + 'auth_user' => 'admin' // 用户信息表 +]; +~~~ + +## 导入数据表 + +~~~php +/* +-- ---------------------------- +-- tp_admin,用户表, +-- id:主键,is_admin:是否是管理员 +-- ---------------------------- + DROP TABLE IF EXISTS `tp_admin`; +CREATE TABLE `tp_admin` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '管理员ID', + `is_admin` tinyint(1) NOT NULL DEFAULT '0', + `username` varchar(50) NOT NULL DEFAULT '' COMMENT '管理员用户名', + `fullname` varchar(50) NOT NULL DEFAULT '', + `phone` varchar(20) NOT NULL DEFAULT '', + `password_reset_token` varchar(255) NOT NULL DEFAULT '', + `access_token` varchar(32) NOT NULL DEFAULT '', + `email` varchar(255) NOT NULL DEFAULT '' COMMENT '邮箱', + `password` varchar(32) NOT NULL DEFAULT '' COMMENT '管理员密码', + `login_times` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '登陆次数', + `login_ip` varchar(20) NOT NULL DEFAULT '' COMMENT 'IP地址', + `login_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '登陆时间', + `last_login_ip` varchar(255) NOT NULL DEFAULT '' COMMENT '上次登陆ip', + `last_login_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '上次登陆时间', + `user_agent` varchar(500) NOT NULL DEFAULT '' COMMENT 'user_agent', + `create_time` int(10) unsigned NOT NULL DEFAULT '0', + `update_time` int(10) NOT NULL DEFAULT '0', + `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1可用0禁用', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4; +-- ---------------------------- +-- tp_auth_rule,规则表, +-- id:主键,name:规则唯一标识, title:规则中文名称 status 状态:为1正常,为0禁用,condition:规则表达式,为空表示存在就验证,不为空表示按照条件验证 +-- ---------------------------- + DROP TABLE IF EXISTS `tp_auth_rule`; +CREATE TABLE `tp_auth_rule` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `name` char(80) NOT NULL DEFAULT '', + `title` char(20) NOT NULL DEFAULT '', + `type` tinyint(1) NOT NULL DEFAULT '1', + `status` tinyint(1) NOT NULL DEFAULT '1', + `condition` char(100) NOT NULL DEFAULT '', # 规则附件条件,满足附加条件的规则,才认为是有效的规则 + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4; +-- ---------------------------- +-- tp_auth_group 用户组表, +-- id:主键, title:用户组中文名称, rules:用户组拥有的规则id, 多个规则","隔开,status 状态:为1正常,为0禁用 +-- ---------------------------- + DROP TABLE IF EXISTS `tp_auth_group`; +CREATE TABLE `tp_auth_group` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `title` char(100) NOT NULL DEFAULT '', + `status` tinyint(1) NOT NULL DEFAULT '1', + `rules` char(80) NOT NULL DEFAULT '', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4; +-- ---------------------------- +-- tp_auth_group_access 用户组明细表 +-- uid:用户id,group_id:用户组id +-- ---------------------------- +DROP TABLE IF EXISTS `tp_auth_group_access`; +CREATE TABLE `tp_auth_group_access` ( + `uid` mediumint(8) unsigned NOT NULL, + `group_id` mediumint(8) unsigned NOT NULL, + UNIQUE KEY `uid_group_id` (`uid`,`group_id`), + KEY `uid` (`uid`), + KEY `group_id` (`group_id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4; + */ +~~~ + +~~~php + +/** + * 权限认证类 + * 功能特性: + * 1,是对规则进行认证,不是对节点进行认证。用户可以把节点当作规则名称实现对节点进行认证。 + * $auth = new \taoser\think\Auth(); $auth->check('规则名称','用户id') + * 2,可以同时对多条规则进行认证,并设置多条规则的关系(or或者and) + * $auth = new \taoser\think\Auth(); $auth->check('规则1,规则2','用户id','and') + * 第三个参数为and时表示,用户需要同时具有规则1和规则2的权限。 当第三个参数为or时,表示用户值需要具备其中一个条件即可。默认为or + * 3,一个用户可以属于多个用户组(tp_auth_group_access表 定义了用户所属用户组)。我们需要设置每个用户组拥有哪些规则(tp_auth_group 定义了用户组权限) + * + * 4,支持规则表达式。 + * 在tp_auth_rule 表中定义一条规则时,如果type为1, condition字段就可以定义规则表达式。 如定义{score}>5 and {score}<100 表示用户的分数在5-100之间时这条规则才会通过。 + */ + +~~~ + + +## 原理 +Auth权限认证是按规则进行认证。 +在数据库中我们有 + +- 规则表(think_auth_rule) +- 用户组表(think_auth_group) +- 用户组明显表(think_auth_group_access) + +我们在规则表中定义权限规则, 在用户组表中定义每个用户组有哪些权限规则,在用户组明显表中定义用户所属的用户组。 + +//命名空间为 +namespace taoser\think; + +//直接使用 +$auth = new \taoser\think\Auth(); + +// 引入类库 +use think\auth\Auth; +$auth = new Auth(); + +// 检测权限 +if($auth->check('show_button',1)){// 第一个参数是规则名称,第二个参数是用户UID + //有显示操作按钮的权限 +}else{ + //没有显示操作按钮的权限 +} + +## 实例 +~~~php + //以下实例以thinkphp5.1为例说明 + Auth类也可以对节点进行认证,我们只要将规则名称,定义为节点名称就行了。 +可以在公共控制器Base中定义_initialize方法 +~~~ + +~~~php +redirect('login/index'); + } + $auth = new Auth(); + $controller = strtolower(request()->controller()); + $action = strtolower(request()->action()); + $url = $controller . "/" . $action; + if (!$auth->check($url, session('admin_id'))) { + $this->error('抱歉,您没有操作权限'); + } + } +} +~~~ + +~~~php +100 and {score}<200 +//name字段:grade3 condition字段:{score}>200 and {score}<300 + +//这里 {score} 表示 think_members 表 中字段 score 的值。 + +//那么这时候 + +$auth = new \taoser\think\Auth(); +$auth->check('grade1', 1); //是判断用户积分是不是0-100 +$auth->check('grade2', 1); //判断用户积分是不是在100-200 +$auth->check('grade3', 1); //判断用户积分是不是在200-300 + +~~~ + + +~~~php +redirect('login/index'); + } + $auth = new \taoser\think\Auth(); + $controller = strtolower(request()->controller()); + $action = strtolower(request()->action()); + $url = $controller . "/" . $action; + $data = Db::name('auth_rule')->order('sort','asc')->select(); + $data = list_to_tree($data); + //排除不需要验证的规则 + $no_check_default = ['index/index']; + $no_check_status_list = Db::name('auth_rule')->where('status', 0)->column('name'); + $no_check_rules_list = explode(',', strtolower(implode(',', array_merge($no_check_default, (array)$no_check_status_list)))); + $no_check_user_list = Db::name('admin')->where('is_admin', 1)->column('id'); + if (!in_array(session('admin_id'), $no_check_user_list)) { + if (!in_array($url, $no_check_rules_list)) { + if (!$auth->check($url, session('admin_id'))) { + $this->error('抱歉,您没有操作权限'); + } + } + foreach ($data as $k => $v) { + if (!$auth->check($v['name'], session('admin_id'))) { + unset($data[$k]); + } else { + if (isset($v['_child'])) { + foreach ($v['_child'] as $key => $value) { + if (!$auth->check($value['name'], session('admin_id'))) { + unset($data[$k]['_child'][$key]); + } + } + } + } + } + } + //unset($data[0]['_child'][0]); + //var_dump($data); + //mysql不区分字段内容大小写 + $active_id = Db::name('auth_rule')->where('name', '=', $url)->field('id,pid,top_pid')->find(); + $this->assign([ + 'active_id' => implode(',', (array)$active_id), + 'menu_nav' => $data, + 'crumb_list' => get_crumb_list($url) + ]); + } +} +~~~ \ No newline at end of file diff --git a/vendor/taoser/think-auth/composer.json b/vendor/taoser/think-auth/composer.json new file mode 100644 index 0000000..4df28de --- /dev/null +++ b/vendor/taoser/think-auth/composer.json @@ -0,0 +1,30 @@ +{ + "name": "taoser/think-auth", + "description": "The Auth package forThinkphp6,ThinkPHP6的Auth权限扩展", + "keywords": ["think-auth", "thinkphp6"], + "homepage": "https://github.com/taoser/think-auth", + "license": "Apache-2.0", + "type": "think-extend", + "authors": [ + { + "name": "taoser", + "email": "changlin_zhao@qq.com" + } + ], + "require": { + "php": ">=7.1.0", + "topthink/framework": "^6.0" + }, + "autoload": { + "psr-4": { + "taoser\\think\\": "src/" + } + }, + "extra": { + "think": { + "config": { + "auth": "src/config/auth.php" + } + } + } +} diff --git a/vendor/taoser/think-auth/src/Auth.php b/vendor/taoser/think-auth/src/Auth.php new file mode 100644 index 0000000..61488e9 --- /dev/null +++ b/vendor/taoser/think-auth/src/Auth.php @@ -0,0 +1,327 @@ + +// +---------------------------------------------------------------------- +namespace taoser\think; + +use think\facade\Db; +use think\facade\Config; +use think\facade\Session; + +/** + * 权限认证类 + * 功能特性: + * 1,是对规则进行认证,不是对节点进行认证。用户可以把节点当作规则名称实现对节点进行认证。 + * $auth=new Auth(); $auth->check('规则名称','用户id') + * 2,可以同时对多条规则进行认证,并设置多条规则的关系(or或者and) + * $auth=new Auth(); $auth->check('规则1,规则2','用户id','and') + * 第三个参数为and时表示,用户需要同时具有规则1和规则2的权限。 当第三个参数为or时,表示用户值需要具备其中一个条件即可。默认为or + * 3,一个用户可以属于多个用户组(think_auth_group_access表 定义了用户所属用户组)。我们需要设置每个用户组拥有哪些规则(think_auth_group 定义了用户组权限) + * + * 4,支持规则表达式。 + * 在think_auth_rule 表中定义一条规则时,如果type为1, condition字段就可以定义规则表达式。 如定义{score}>5 and {score}<100 表示用户的分数在5-100之间时这条规则才会通过。 + */ +//数据库 +/* +-- ---------------------------- +-- tp_admin,用户表, +-- id:主键,is_admin:是否是管理员 +-- ---------------------------- + DROP TABLE IF EXISTS `tp_admin`; +CREATE TABLE `tp_admin` ( + `id` int(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '管理员ID', + `is_admin` tinyint(1) NOT NULL DEFAULT '0', + `username` varchar(50) NOT NULL DEFAULT '' COMMENT '管理员用户名', + `fullname` varchar(50) NOT NULL DEFAULT '', + `phone` varchar(20) NOT NULL DEFAULT '', + `password_reset_token` varchar(255) NOT NULL DEFAULT '', + `access_token` varchar(32) NOT NULL DEFAULT '', + `email` varchar(255) NOT NULL DEFAULT '' COMMENT '邮箱', + `password` varchar(32) NOT NULL DEFAULT '' COMMENT '管理员密码', + `login_times` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '登陆次数', + `login_ip` varchar(20) NOT NULL DEFAULT '' COMMENT 'IP地址', + `login_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '登陆时间', + `last_login_ip` varchar(255) NOT NULL DEFAULT '' COMMENT '上次登陆ip', + `last_login_time` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '上次登陆时间', + `user_agent` varchar(500) NOT NULL DEFAULT '' COMMENT 'user_agent', + `create_time` int(10) unsigned NOT NULL DEFAULT '0', + `update_time` int(10) NOT NULL DEFAULT '0', + `status` tinyint(1) NOT NULL DEFAULT '1' COMMENT '1可用0禁用', + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8; +-- ---------------------------- +-- think_auth_rule,规则表, +-- id:主键,name:规则唯一标识, title:规则中文名称 status 状态:为1正常,为0禁用,condition:规则表达式,为空表示存在就验证,不为空表示按照条件验证 +-- ---------------------------- +DROP TABLE IF EXISTS `think_auth_rule`; +CREATE TABLE `think_auth_rule` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `name` char(80) NOT NULL DEFAULT '', + `title` char(20) NOT NULL DEFAULT '', + `type` tinyint(1) NOT NULL DEFAULT '1', + `status` tinyint(1) NOT NULL DEFAULT '1', + `condition` char(100) NOT NULL DEFAULT '', # 规则附件条件,满足附加条件的规则,才认为是有效的规则 + PRIMARY KEY (`id`), + UNIQUE KEY `name` (`name`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +-- ---------------------------- +-- think_auth_group 用户组表, +-- id:主键, title:用户组中文名称, rules:用户组拥有的规则id, 多个规则","隔开,status 状态:为1正常,为0禁用 +-- ---------------------------- +DROP TABLE IF EXISTS `think_auth_group`; + CREATE TABLE `think_auth_group` ( + `id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT, + `title` char(100) NOT NULL DEFAULT '', + `status` tinyint(1) NOT NULL DEFAULT '1', + `rules` char(80) NOT NULL DEFAULT '', + PRIMARY KEY (`id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; +-- ---------------------------- +-- think_auth_group_access 用户组明细表 +-- uid:用户id,group_id:用户组id +-- ---------------------------- +DROP TABLE IF EXISTS `think_auth_group_access`; + CREATE TABLE `think_auth_group_access` ( + `uid` mediumint(8) unsigned NOT NULL, + `group_id` mediumint(8) unsigned NOT NULL, + UNIQUE KEY `uid_group_id` (`uid`,`group_id`), + KEY `uid` (`uid`), + KEY `group_id` (`group_id`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + */ + +class Auth +{ + /** + * @var object 对象实例 + */ + protected static $instance; + /** + * 当前请求实例 + * @var Request + */ + protected $request; + + //默认配置 + protected $config = [ + 'auth_on' => true, // 权限开关 + 'auth_type' => 1, // 认证方式,1为实时认证;2为登录认证。 + 'auth_group' => 'auth_group', // 用户组数据表名 + 'auth_group_access' => 'auth_group_access', // 用户-用户组关系表 + 'auth_rule' => 'auth_rule', // 权限规则表 + 'auth_user' => 'admin', // 用户信息表 + ]; + + /** + * 类架构函数 + * Auth constructor. + */ + public function __construct() + { + //可设置配置项 auth, 此配置项为数组。 + if ($auth = Config::get('auth')) { + $this->config = array_merge($this->config, $auth); + } + // 初始化request + $this->request = request(); + } + + /** + * 初始化 + * @access public + * @param array $options 参数 + * @return \think\Request + */ + public static function instance($options = []) + { + if (is_null(self::$instance)) { + self::$instance = new static($options); + } + return self::$instance; + } + + /** + * 检查权限 + * @param $name string|array 需要验证的规则列表,支持逗号分隔的权限规则或索引数组 + * @param $uid int 认证用户的id + * @param int $type 认证类型 + * @param string $mode 执行check的模式 + * @param string $relation 如果为 'or' 表示满足任一条规则即通过验证;如果为 'and'则表示需满足所有规则才能通过验证 + * @return bool 通过验证返回true;失败返回false + */ + public function check($name, $uid, $type = 1, $mode = 'url', $relation = 'or') + { + if (!$this->config['auth_on']) { + return true; + } + // 获取用户需要验证的所有有效规则列表 + $authList = $this->getAuthList($uid, $type); + if (is_string($name)) { + $name = strtolower($name); + if (strpos($name, ',') !== false) { + $name = explode(',', $name); + } else { + $name = [$name]; + } + } + $list = []; //保存验证通过的规则名 + if ('url' == $mode) { + $REQUEST = unserialize(strtolower(serialize($this->request->param()))); + } + foreach ($authList as $auth) { + $query = preg_replace('/^.+\?/U', '', $auth); + if ('url' == $mode && $query != $auth) { + parse_str($query, $param); //解析规则中的param + $intersect = array_intersect_assoc($REQUEST, $param); + $auth = preg_replace('/\?.*$/U', '', $auth); + if (in_array($auth, $name) && $intersect == $param) { + //如果节点相符且url参数满足 + $list[] = $auth; + } + } else { + if (in_array($auth, $name)) { + $list[] = $auth; + } + } + } + if ('or' == $relation && !empty($list)) { + return true; + } + $diff = array_diff($name, $list); + if ('and' == $relation && empty($diff)) { + return true; + } + + return false; + } + + /** + * 根据用户id获取用户组,返回值为数组 + * @param $uid int 用户id + * @return array 用户所属的用户组 array( + * array('uid'=>'用户id','group_id'=>'用户组id','title'=>'用户组名称','rules'=>'用户组拥有的规则id,多个,号隔开'), + * ...) + */ + public function getGroups($uid) + { + static $groups = []; + if (isset($groups[$uid])) { + return $groups[$uid]; + } + // 转换表名 + $auth_group_access = $this->parseName($this->config['auth_group_access'], 1); + $auth_group = $this->parseName($this->config['auth_group'], 1); + // 执行查询 + $user_groups = Db::view($auth_group_access, 'uid,group_id') + ->view($auth_group, 'title,rules', "{$auth_group_access}.group_id={$auth_group}.id", 'LEFT') + ->where("{$auth_group_access}.uid='{$uid}' and {$auth_group}.status='1'") + ->select(); + $groups[$uid] = $user_groups ?: []; + + return $groups[$uid]; + } + + /** + * 获得权限列表 + * @param integer $uid 用户id + * @param integer $type + * @return array + */ + protected function getAuthList($uid, $type) + { + static $_authList = []; //保存用户验证通过的权限列表 + $t = implode(',', (array)$type); + if (isset($_authList[$uid . $t])) { + return $_authList[$uid . $t]; + } + if (2 == $this->config['auth_type'] && Session::has('_auth_list_' . $uid . $t)) { + return Session::get('_auth_list_' . $uid . $t); + } + //读取用户所属用户组 + $groups = $this->getGroups($uid); + $ids = []; //保存用户所属用户组设置的所有权限规则id + foreach ($groups as $g) { + $ids = array_merge($ids, explode(',', trim($g['rules'], ','))); + } + $ids = array_unique($ids); + if (empty($ids)) { + $_authList[$uid . $t] = []; + return []; + } + + //读取用户组所有权限规则 + + $map[] = ['id', 'in', $ids]; + $map[] = ['status', '=', 1]; + + $rules = Db::name($this->config['auth_rule'])->where($map)->field('condition,name')->select(); + //循环规则,判断结果。 + $authList = []; // + foreach ($rules as $rule) { + if (!empty($rule['condition'])) { + //根据condition进行验证 + $user = $this->getUserInfo($uid); //获取用户信息,一维数组 + $command = preg_replace('/\{(\w*?)\}/', '$user[\'\\1\']', $rule['condition']); + //dump($command); //debug + @(eval('$condition=(' . $command . ');')); + if ($condition) { + $authList[] = strtolower($rule['name']); + } + } else { + //只要存在就记录 + $authList[] = strtolower($rule['name']); + } + } + $_authList[$uid . $t] = $authList; + if (2 == $this->config['auth_type']) { + //规则列表结果保存到session + Session::set('_auth_list_' . $uid . $t, $authList); + } + + return array_unique($authList); + } + + /** + * 获得用户资料,根据自己的情况读取数据库 + */ + protected function getUserInfo($uid) + { + static $userinfo = []; + + $user = Db::name($this->config['auth_user']); + // 获取用户表主键 + $_pk = is_string($user->getPk()) ? $user->getPk() : 'uid'; + if (!isset($userinfo[$uid])) { + $userinfo[$uid] = $user->where($_pk, $uid)->find(); + } + + return $userinfo[$uid]; + } + + /** + * 字符串命名风格转换 + * type 0 将Java风格转换为C的风格 1 将C风格转换为Java的风格 + * @access public + * @param string $name 字符串 + * @param integer $type 转换类型 + * @param bool $ucfirst 首字母是否大写(驼峰规则) + * @return string + */ + public function parseName($name, $type = 0, $ucfirst = true) + { + if ($type) { + $name = preg_replace_callback('/_([a-zA-Z])/', function ($match) { + return strtoupper($match[1]); + }, $name); + return $ucfirst ? ucfirst($name) : lcfirst($name); + } + + return strtolower(trim(preg_replace("/[A-Z]/", "_\\0", $name), "_")); + } +} diff --git a/vendor/taoser/think-auth/src/config/auth.php b/vendor/taoser/think-auth/src/config/auth.php new file mode 100644 index 0000000..761c4f9 --- /dev/null +++ b/vendor/taoser/think-auth/src/config/auth.php @@ -0,0 +1,13 @@ + true, // 认证开关 + 'auth_type' => 1, // 认证方式,1为实时认证;2为登录认证。 + 'auth_group' => 'auth_group', // 用户组数据表名 + 'auth_group_access' => 'auth_group_access', // 用户-用户组关系表 + 'auth_rule' => 'auth_rule', // 权限规则表 + 'auth_user' => 'admin' // 用户信息表 +];