天天看點

Auth權限管理

1. 簡介

Auth權限管理比RBAC更加靈活,auth對權限的控制更為精細。

Auth的特性:

  • 是對規則進行認證,不是對節點進行認證。使用者可以把節點當作規則名稱實作對節點進行認證。 auth=newAuth(); auth->check(‘規則名稱’,’使用者id’)
  • 可以同時對多條規則進行認證,并設定多條規則的關系(or或者and)。 auth=newAuth(); auth->check(‘規則1,規則2’,’使用者id’,’and’)
  • 一個使用者可以屬于多個使用者組(think_auth_group_access表 定義了使用者所屬使用者組),我們需要設定每個使用者組擁有哪些規則(think_auth_group 定義了使用者組的權限)。
  • 支援規則表達式。在think_auth_rule 表中定義一條規則時,如果type為1, condition字段就可以定義規則表達式。 如定義{score}>50 and {score}<100 表示使用者的分數在50-100之間時這條規則才會通過。

2. 基本用法

以ThinkPHP3.2.3為例,進行簡單介紹。

Auth類檔案為ThinkPHP\Library\Think\Auth.class.php,預設的認證方式為實時認證。

建立四張資料表。

# 使用者表
CREATE TABLE IF NOT EXISTS `think_user` (
  `uid` mediumint() unsigned NOT NULL AUTO_INCREMENT COMMENT '使用者id',
  `username` varchar() NOT NULL DEFAULT '' COMMENT '使用者名',
  `password` char() NOT NULL DEFAULT '' COMMENT '密碼',
  `status` tinyint() unsigned NOT NULL DEFAULT  COMMENT '狀态:0禁用,1正常',
  `score` mediumint() unsigned NOT NULL DEFAULT  COMMENT '積分',
  `login_time` int() unsigned NOT NULL DEFAULT  COMMENT '最近一次登入時間',
  `login_ip` int() NOT NULL DEFAULT '0' COMMENT '最近一次登入ip',
  PRIMARY KEY (`uid`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='使用者表';

# 使用者-使用者組關系表
CREATE TABLE IF NOT EXISTS `think_auth_group_access` (  
    `uid` mediumint() unsigned NOT NULL DEFAULT  COMMENT '使用者id',  
    `group_id` mediumint() unsigned NOT NULL DEFAULT  COMMENT '組id', 
    UNIQUE KEY `uid_group_id` (`uid`,`group_id`),  
    KEY `uid` (`uid`), 
    KEY `group_id` (`group_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='使用者-使用者組關系表';

# 規則表
CREATE TABLE IF NOT EXISTS `think_auth_rule` (  
    `id` mediumint() unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵',  
    `name` char() NOT NULL DEFAULT '' COMMENT '規則的唯一辨別(英文)',  
    `title` char() NOT NULL DEFAULT '' COMMENT '規則的中文名稱',  
    `type` tinyint() NOT NULL DEFAULT '1',    
    `status` tinyint() NOT NULL DEFAULT '1' COMMENT '狀态:1正常,0禁用',  
    `condition` char() NOT NULL DEFAULT '' COMMENT '規則的附加條件',  
    PRIMARY KEY (`id`),  
    UNIQUE KEY `name` (`name`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COMMENT='規則表';

# 使用者組表
CREATE TABLE IF NOT EXISTS `think_auth_group` ( 
    `id` mediumint() unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵', 
    `title` char() NOT NULL DEFAULT '' COMMENT '使用者組的中文名稱', 
    `status` tinyint() NOT NULL DEFAULT '1' COMMENT '狀态:0禁用,1正常', 
    `rules` char() NOT NULL DEFAULT '' COMMENT '使用者組擁有的規則id, 多個規則用,隔開', 
    PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 COMMENT '使用者組表';
           

子產品配置檔案D:\xampp\htdocs\test\Application\Adm\Conf\config.php的代碼如下:

<?php
return array(
    //'配置項'=>'配置值'

    // 資料庫配置
    'DB_TYPE'               =>  'mysql',        // 資料庫類型
    'DB_HOST'               =>  '127.0.0.1',    // 伺服器位址
    'DB_NAME'               =>  'auth',         // 資料庫名
    'DB_USER'               =>  'root',     // 使用者名
    'DB_PWD'                =>  '123456',   // 密碼
    'DB_PORT'               =>  '3306',     // 端口
    'DB_PREFIX'             =>  'think_',   // 資料庫表字首

    // auth權限驗證的配置
    'AUTH_CONFIG' => array(
            'AUTH_ON'           => true,                // 認證開關
            'AUTH_TYPE'         => ,                   // 認證方式:1為實時認證,2為登入認證。
            'AUTH_GROUP'        => 'think_auth_group',        // 使用者組表
            'AUTH_GROUP_ACCESS' => 'think_auth_group_access', // 使用者-使用者組關系表
            'AUTH_RULE'         => 'think_auth_rule',         // 權限規則表
            'AUTH_USER'         => 'think_user',              // 使用者表
    ),
);
           

測試資料如下:

使用者表(think_user):

uid username password status score login_time login_ip
1 admin e10adc3949ba59abbe56e057f20f883e 1
2 user01 e10adc3949ba59abbe56e057f20f883e 1
3 user02 e10adc3949ba59abbe56e057f20f883e 1 60 1497321747 2130706433

規則表(think_auth_rule):

id name title type status condition
1 adm/index/index 背景首頁 1 1
2 adm/index/test 測試頁面 1 1 {score}>50 and {score}<100

使用者組表(think_auth_group)

id title status rules
1 普通會員 1 1
2 黃金會員 1 1,2

使用者-使用者組關系表(think_auth_group_access)

uid group_id
2 1
3 2

D:\xampp\htdocs\test\Application\Adm\Controller\PublicController.class.php的代碼如下:

<?php
namespace Adm\Controller;
use Think\Controller;

class PublicController extends Controller {

    /**
     * 使用者登入頁面
     * http://127.0.0.1/test/index.php/public/login
     */
    public function login() {
        $this->display();
    }

    /**
     * 登入送出的位址
     */
    public function login_submit() {
        if(!IS_POST) $this->error('頁面不存在,請稍後再試', U('Public/login'));

        $username = I('username','');
        $password = I('password','');

        $user_info = M('user')->where("username = '$username' AND password = '".md5($password)."'")->find();

        if(!$user_info) $this->error('使用者名或密碼錯誤', U('Public/login'));

        if(!$user_info['status']) $this->error('該使用者已被禁用,暫時不可登入', U('Public/login'));

        // 更新登入資訊
        M('user')->save(array("uid"=> $user_info["uid"], "login_time"=> time(), "login_ip" => ip2long(get_client_ip())));

        // 寫入session
        session('uid', $user_info['uid']);   // 使用者id(uid)
        session('username', $user_info['username']);   // 使用者名

        $this->success('登入成功', U('Index/index'));
    }
}
           

D:\xampp\htdocs\test\Application\Adm\Controller\CommonController.class.php的代碼如下:

<?php
namespace Adm\Controller;
use Think\Controller;

/**
 * @author Administrator
 * 所有需要進行權限驗證的控制器,使其繼承CommonController即可
 */
class CommonController extends Controller {

    /**
     * ThinkPHP中提供了_initialize()方法,在類初始化時,_initialize()方法會自動執行
     */
    protected function _initialize() {

        // 執行個體化auth對象
        $auth = new \Think\Auth();
        $rule_name = strtolower(MODULE_NAME.'/'.CONTROLLER_NAME.'/'.ACTION_NAME);

        // 驗證權限
        $res = $auth->check($rule_name, $_SESSION['uid']);
        if($res === false) $this->error('您沒有權限通路!', U('Public/login'));
    }
}
           

D:\xampp\htdocs\test\Application\Adm\Controller\IndexController.class.php的代碼如下:

<?php
namespace Adm\Controller;

/**
 * @author Administrator
 * 需要進行auth權限驗證的控制器就繼承CommonController
 */
class IndexController extends CommonController {

    /**
     * 背景首頁
     * http://127.0.0.1/test/index.php/index/index
     */
    public function index() {
        dump(session());
        echo '背景首頁!';
    }

    /**
     * 測試頁面
     * http://127.0.0.1/test/index.php/index/test
     */
    public function test() {
        echo MODULE_NAME.'<br/>';
        echo CONTROLLER_NAME.'<br/>';
        echo ACTION_NAME.'<br/>';
        echo '這是測試頁面';
    }

}
           

繼續閱讀