auth權限邏輯


下面本人為大家講解一下如何實現auth權限,
第一步,新建Auth.php,復制下面的代碼,把注釋中的表都創建一下。把文件放到extend新建文件夾org放進去即可,
<?php 
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2011 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: luofei614 <weibo.com/luofei614>
// +----------------------------------------------------------------------
// | 修改者: anuo (本權限類在原3.2.3的基礎上修改過來的)
// +----------------------------------------------------------------------
use think\Db;
use think\Config;
use think\Session;
use think\Request;
use think\Loader; 

/**
 * 權限認證類
 * 功能特性:
 * 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之間時這條規則才會通過。
 */
//數據庫
/*
-- ----------------------------
-- 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'           => 1, // 權限開關
        'auth_type'         => 1, // 認證方式,1為實時認證;2為登錄認證。
        'auth_group'        => 'auth_group', // 用戶組數據表名
        'auth_group_access' => 'auth_group_access', // 用戶-用戶組關系表
        'auth_rule'         => 'auth_rule', // 權限規則表
        'auth_user'         => 'member', // 用戶信息表
    ];

    /**
     * 類架構函數
     * Auth constructor.
     */
    public function __construct()
    {
        //可設置配置項 auth, 此配置項為數組。
        if ($auth = Config::get('auth')) {
            $this->config = array_merge($this->config, $auth);
        }
        // 初始化request
        $this->request = Request::instance();
    }

    /**
     * 初始化
     * @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 = Loader::parseName($this->config['auth_group_access'], 1);
        $auth_group        = Loader::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],
            'type' => $type
        ];
        //讀取用戶組所有權限規則
        $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']);
                @(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);
    }

    /**
     * 獲得用戶資料
     * @param $uid
     * @return mixed
     */
    protected function getUserInfo($uid)
    {
        static $user_info = [];

        $user = Db::name($this->config['auth_user']);
        // 獲取用戶表主鍵
        $_pk = is_string($user->getPk()) ? $user->getPk() : 'uid';
        if (!isset($user_info[$uid])) {
            $user_info[$uid] = $user->where($_pk, $uid)->find();
        }

        return $user_info[$uid];
    }
}
第二步 新建控制器,其它的權限添加就不多說了,下面是驗證最終結果
<?php
namespace app\admin\controller;
use \think\Controller;
use think\Loader;
class Base extends Controller
{
    protected $current_action;
    public function _initialize()
    {
        Loader::import("org/Auth", EXTEND_PATH);
        $auth=new \Auth();
        $this->current_action = request()->module().'/'.request()->controller().'/'.lcfirst(request()->action());
        $result = $auth->check($this->current_action,session('user_id'));
        if($result){
echo
"權限驗證成功"; } } }






來源:https://blog.csdn.net/qq_33257081/article/details/79137190
下面本人為大家講解一下如何實現auth權限,
第一步,新建Auth.php,復制下面的代碼,把注釋中的表都創建一下。把文件放到extend新建文件夾org放進去即可,
<?php // +---------------------------------------------------------------------- // | ThinkPHP [ WE CAN DO IT JUST THINK IT ] // +---------------------------------------------------------------------- // | Copyright (c) 2011 http://thinkphp.cn All rights reserved. // +---------------------------------------------------------------------- // | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 ) // +---------------------------------------------------------------------- // | Author: luofei614 <weibo.com/luofei614> // +---------------------------------------------------------------------- // | 修改者: anuo (本權限類在原3.2.3的基礎上修改過來的) // +---------------------------------------------------------------------- use think\Db; use think\Config; use think\Session; use think\Request; use think\Loader; /** * 權限認證類 * 功能特性: * 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之間時這條規則才會通過。 */ //數據庫 /* -- ---------------------------- -- 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' => 1, // 權限開關 'auth_type' => 1, // 認證方式,1為實時認證;2為登錄認證。 'auth_group' => 'auth_group', // 用戶組數據表名 'auth_group_access' => 'auth_group_access', // 用戶-用戶組關系表 'auth_rule' => 'auth_rule', // 權限規則表 'auth_user' => 'member', // 用戶信息表 ]; /** * 類架構函數 * Auth constructor. */ public function __construct() { //可設置配置項 auth, 此配置項為數組。 if ($auth = Config::get('auth')) { $this->config = array_merge($this->config, $auth); } // 初始化request $this->request = Request::instance(); } /** * 初始化 * @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 = Loader::parseName($this->config['auth_group_access'], 1); $auth_group = Loader::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], 'type' => $type ]; //讀取用戶組所有權限規則 $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']); @(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); } /** * 獲得用戶資料 * @param $uid * @return mixed */ protected function getUserInfo($uid) { static $user_info = []; $user = Db::name($this->config['auth_user']); // 獲取用戶表主鍵 $_pk = is_string($user->getPk()) ? $user->getPk() : 'uid'; if (!isset($user_info[$uid])) { $user_info[$uid] = $user->where($_pk, $uid)->find(); } return $user_info[$uid]; } }
第二步 新建控制器,其它的權限添加就不多說了,下面是驗證最終結果
<?php namespace app\admin\controller; use \think\Controller; use think\Loader; class Base extends Controller {     protected $current_action;     public function _initialize()     {         Loader::import("org/Auth", EXTEND_PATH);         $auth=new \Auth();         $this->current_action = request()->module().'/'.request()->controller().'/'.lcfirst(request()->action());         $result = $auth->check($this->current_action,session('user_id'));         if($result){             echo "權限驗證成功";         }     } }


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM