由于種種機緣巧合用Zend Framework框架做過一年的項目,所以,對ZF框架的相關的包也有著一定的了解,前些天用TP的RBAC發現要用數據庫,而且使用起來也不是很順手,也許是自己有著偏見的緣故吧,于是就放棄了TP提供的RBAC權限,選用了ZEND ACL.
第一步:從Zend官方下載ZF框架包,解壓后將里面的Acl包與Acl包同級目錄下的Acl.php文件也一起拷貝至TP框架提供的第三方類庫目錄Vendor/Zend.
第二步:由于在使用ZEND ACL的時候,我使用了ini格式的配置文件,同時也方便ACL讀取ini文件,這個地方用到了Zend Config這個包,也將這個包拷貝到Vendor/Zend目錄,還有與Config同目錄下的Config.php文件也拷貝到Vendor/Zend目錄.
第三步:由于這兩個包都用到了Zend_Exception這個類,所以,要將Zend目錄下的Exception.php文件拷貝到Vendor目錄下。
注:為什么要有Zend目錄,因為,Acl和Config包都在相互引用類的時候都用到了Zend這個目錄,所以,保證程序正常引用,必須將Acl和Config包放在Vendor/Zend目錄下.
第四步:配置資源,所謂資源就是我們要進行用ACL管理的資源,只有這些資源才會被ACL進行管理,沒有在配置之列的資源將不會適用ACL控制,因為我的程序是使用的分組。所以,在Conf目錄下有一個分組目錄Admin. Admin目錄下我創建了一個acl.ini文件,這個文件用來保存我們要進行控制的資源.
格式如:
;;==========================================
;;訪問控制列表(ACL)設置說明:
;;1、resources為資源列表,僅對資源列表中的資源進行控制
;;2、resources格式:自定義名稱.鍵名(任意,但不可用重復)= 模塊:控制器
;;3、這里將Zend ACL移動到Thinkphp中來使用,這里配置與Zend里面的配置無二。
;; admin指的要將此運用到哪個分組[這里Admin分組],如果沒有分組是獨立的,那么隨機設置一個。在ACL類里面自己匹配。
;; 這里必須將'admin:'后面的小寫,不管你的操作是大寫還是小寫,這里都必須小寫。
;;==========================================
- [ACL]
- ;;====resource資源部分
- resource.index = Admin:index
- resource.ad = Admin:ad
- resource.article = Admin:article
- resource.grievance = Admin:grievance
- resource.login = Admin:login
- resource.secret = Admin:secret
- resource.user = Admin:user
- resource.common = Admin:common
第五步:創建控制類,有了資源,我們還要指定角色與分配資源,因為,一般后臺程序或其他管理程序同時會有多個角色進行操作,而每個角色所能操作的權限不同,不同的權限對應的資源也不一樣,所以,我們要通過這個類來細化規則,如下:
- class AdminAcl
- {
- // 默認角色
- private $_defaultRole = 'guest';
- public function __construct()
- {
- Vendor('Zend.Acl');
- Vendor('Zend.Config.ini');
- $this->acl = new Zend_Acl();
- // 定義了三個角色:默認[游客]角色、客服角色、超級管理員角色。
- $this->acl->addRole(new Zend_Acl_Role($this->_defaultRole));
- $this->acl->addRole(new Zend_Acl_Role('service'));
- $this->acl->addRole(new Zend_Acl_Role('admin'));
- // 讀取配置文件。配置文件指明了需要進行控制的類型。
- $aclConfig = new Zend_Config_Ini(APP_PATH . '/Conf/Admin/acl.ini', 'ACL');
- $aclSettings = $aclConfig->toArray();
- // 添加資源
- foreach ($aclSettings as $key => $arr) {
- $this->acl->add(new Zend_Acl_Resource($key));
- foreach ($arr as $value){
- $this->acl->add(new Zend_Acl_Resource($value), $key);
- }
- }
- // 游客權限,可以訪問的資源:這里只能訪問登錄模塊的index
- // 第三個參數是用戶可以訪問的操作。
- $this->acl->allow('guest', 'Admin:login', array('index'));
- // 客服權限。
- $this->acl->allow('service', 'Admin:login');
- $this->acl->allow('service', 'Admin:index');
- $this->acl->allow('service', 'Admin:ad');
- $this->acl->allow('service', 'Admin:article');
- $this->acl->allow('service', 'Admin:grievance');
- $this->acl->allow('service', 'Admin:secret');
- //$this->acl->allow('service', 'admin:user'); // 用戶管理必須超級管理員。
- //$this->acl->allow('service', 'admin:common');
- // 超級管理員可以訪問任意資源
- $this->acl->allow('admin');
- $this->preDispatch();
- }
- public function preDispatch()
- {
- $role = $this->_defaultRole; // 默認角色為游客。
- // 首先第一步取用戶信息,相關的驗證放到這里即可。
- $is_login = true;
- if ($is_login)
- {
- $userinfo = array('usertype' => 3);
- if ($userinfo['usertype'] == 1)
- {
- $role = 'admin';
- }
- elseif ($userinfo['usertype'] == 2)
- {
- $role = 'service';
- }
- }
- // 判斷角色是否在注冊的角色里面。
- if (!$this->acl->hasRole($role))
- {
- $role = 'guest';
- }
- $group_name = GROUP_NAME;
- $module_name = strtolower(MODULE_NAME);
- $action_name = strtolower(ACTION_NAME);
- $resource = "$group_name:$module_name";
- if (!$this->acl->has($resource))
- {
- $resource = null;
- }
- // 若是沒有權限則將跳轉到登錄頁面。
- if (!$this->acl->isAllowed($role, $resource, $action_name))
- {
- redirect(U('Admin-Login/index'));
- }
- }
- }
注:APP_PATH 這個是一個常量,這個常量我在項目入口文件index.php文件中定義了,它的值是入口文件所在目錄,這樣的話,就相當于當前項目的目錄路徑,因為我剛才將acl.ini放在了Conf/Admin目錄下了.
以上這個類我們放在了項目目錄下的Commmon/Admin分組目錄下,取名為AdminAcl.class.php.
第六步:在調用任何操作之前調用此控制類,這一步就很簡單了,因為,我們在做項目的時候都會把會創建一個CommonAction.class.php文件或類讓其他所有的Action繼承,所以,這個我在CommonAction類里的_initialize()方法里面進行調用控制類.調用方法如:
- public function _initialize()
- {
- import('AdminAcl', 'Common/Admin');
- new AdminAcl();
- }
這樣每次執行其他Action的時候都會調用執行這個初始化方法,就會自動調用AdminAcl這個資源控制類,就會按照這個類中的preDespatch()方法的規則進行判斷控制.
結后語:其實在第五步的時候,最后我們調用了redirect()方法進行跳轉,這個方法是TP系統函數,里面的URL地址可以配置在分組配置中,這樣達到一個全自動或半自動的效果.
以上用法在ZF里面是非常常見的,如果TP使用不到,那在ZF框架里面一定會用到.
新聞熱點
疑難解答
圖片精選