實現簡單的ACL

 

Php代碼 

<?php 

/**

 * 簡單的ACL 權限控制功能

 * 

 * 表定義

 * 

 * 1. 資源定義    (rsid,access,desc)

 * 2. 角色定義    (id,rolename,desc)

 * 3. 資源-角色關聯(rsid,role_id)

 * 4. 用戶-角色關聯(user_id,role_id)

 * 

 * 依賴db.php sqlobject.php

 * 

 * @author vb2005xu.iteye.com 

 */ 

class AclBase { 

 

    /**

     * 不允許任何人訪問

     */ 

    const NOBODY = 0; 

     

    /**

     * 允許任何人訪問

     */ 

    const EVERYONE = 1; 

     

    /**

     * 允許 擁有角色的用戶訪問

     */ 

    const HAS_ROLE = 2; 

     

    /**

     * 允許 不帶有角色的用戶訪問

     */ 

    const NO_ROLE = 3; 

 

    /**

     * 在 資源-角色關聯 定義的 角色才能訪問

     */ 

    const ALLOCATE_ROLES = 4; 

     

    // 定義相關的 表名 

    public $tbResources = 'aclresources'; 

    public $tbRoles = 'aclroles'; 

    public $tbRefResourcesRoles = 'aclresources_aclroles'; 

    public $tbRefUsersRoles = 'users_aclroles'; 

     

    /**

     * 格式化 資源的訪問權限並返回

     * 

     * @return int

     */ 

    static function formatAccessValue($access){ 

        static $arr = array(self::NOBODY,self::EVERYONE,self::HAS_ROLE,self::NO_ROLE,self::ALLOCATE_ROLES); 

        return in_array($access,$arr) ? $access : self::NOBODY; 

    } 

     

    /**

     * 創建資源,返回資源記錄主鍵

     * 

     * @param string $rsid

     * @param int $access

     * @param string $desc

     * 

     * @return int

     */ 

    function createResource($rsid,$access,$desc){ 

        if (emptyempty($rsid)) return false; 

         

        $resource = array( 

            'rsid' => $rsid, 

            'access' => self::formatAccessValue($access), 

            'desc' => $desc, 

            'created_at' => CURRENT_TIMESTAMP 

        ); 

         

        return SingleTableCRUD::insert($this->tbResources,$resource); 

    } 

     

    /**

     * 修改資源,返回成功狀態

     * 

     * @param array $resource

     * @return int

     */ 

    function updateResource(array $resource){        

        if (!isset($resource['rsid'])) return false; 

         

        $resource['updated_at'] = CURRENT_TIMESTAMP; 

         

        return SingleTableCRUD::update($this->tbResources,$resource,'rsid'); 

    } 

     

    /**

     * 刪除資源

     * 

     * @param string $rsid

     * @return int

     */ 

    function deleteResource($rsid){ 

        if (emptyempty($rsid)) return false; 

        return SingleTableCRUD::delete($this->tbResources,array('rsid'=>$rsid)); 

    } 

     

    /**

     * 創建角色,返回角色記錄主鍵

     * 

     * @param string $rolename

     * @param string $desc

     * 

     * @return int

     */ 

    function createRole($rolename,$desc){ 

        if (emptyempty($rolename)) return false; 

         

        $role = array( 

            'rolename' => $rolename, 

            'desc' => $desc, 

            'created_at' => CURRENT_TIMESTAMP 

        ); 

         

        return SingleTableCRUD::insert($this->tbRoles,$role); 

    } 

     

    /**

     * 修改角色,返回成功狀態

     * 

     * @param array $role

     * @return int

     */ 

    function updateRole(array $role){        

        if (!isset($role['id'])) return false; 

         

        if (isset($role['rolename'])) unset($role['rolename']); 

        $role['updated_at'] = CURRENT_TIMESTAMP; 

         

        return SingleTableCRUD::update($this->tbRoles,$role,'id'); 

    } 

     

    /**

     * 刪除角色

     * 

     * @param int $role_id

     * @return int

     */ 

    function deleteRole($role_id){ 

        if (emptyempty($role_id)) return false; 

        return SingleTableCRUD::delete($this->tbRoles,array('role_id'=>(int) $role_id)); 

    } 

     

    /**

     * 為資源指定角色,每次均先全部移除表中相關記錄再插入

     * 

     * @param int $rsid

     * @param mixed $roleIds

     * @param boolean $setNull 當角色id不存在時,是否將資源從關聯表中清空

     */ 

    function allocateRolesForResource($rsid,$roleIds,$setNull=false,$defaultAccess=-1){ 

        if (emptyempty($rsid)) return false; 

         

        $roleIds = normalize($roleIds,','); 

        if (emptyempty($roleIds)){ 

            if ($setNull){ 

                SingleTableCRUD::delete($this->tbRefResourcesRoles,array('rsid'=>$rsid)); 

                 

                if ($defaultAccess != -1){ 

                    $defaultAccess = self::formatAccessValue($defaultAccess); 

                    $this->updateResource(array('rsid'=>$rsid,'access'=>$defaultAccess)); 

                } 

                return true;  

            } 

            return false; 

        } 

         

        SingleTableCRUD::delete($this->tbRefResourcesRoles,array('rsid'=>$rsid)); 

         

        $roleIds = array_unique($roleIds); 

         

        foreach ($roleIds as $role_id){ 

            SingleTableCRUD::insert($this->tbRefResourcesRoles,array('rsid'=>$rsid,'role_id'=>(int)$role_id)); 

        } 

        return true; 

    } 

     

    function cleanRolesForResource($rsid){ 

        if (emptyempty($rsid)) return false; 

        return SingleTableCRUD::delete($this->tbRefResourcesRoles,array('rsid'=>$rsid)); 

    } 

     

    function cleanResourcesForRole($role_id){ 

        if (emptyempty($role_id)) return false; 

        return SingleTableCRUD::delete($this->tbRefResourcesRoles,array('role_id'=>(int) $role_id)); 

    } 

     

    /**

     * 為角色分配資源,每次均先全部移除表中相關記錄再插入

     * 

     * @param int $role_id

     * @param mixed $rsids

     * 

     * @return boolean

     */ 

    function allocateResourcesForRole($role_id,$rsids){ 

        if (emptyempty($role_id)) return false; 

         

        $role_id = (int) $role_id; 

        $rsids = normalize($rsids,','); 

        if (emptyempty($rsids)){ 

            return false;        

        } 

         

        SingleTableCRUD::delete($this->tbRefResourcesRoles,array('role_id'=>$role_id)); 

         

        $rsids = array_unique($rsids); 

         

        foreach ($rsids as $rsid){ 

            SingleTableCRUD::insert($this->tbRefResourcesRoles,array('rsid'=>$rsid,'role_id'=>$role_id)); 

        } 

        return true; 

    } 

     

    /**

     * 為用戶指派角色,每次均先全部移除表中相關記錄再插入

     * 

     * 此處在用戶很多的時候可能會有性能問題… 後面再想怎麼優化

     * 

     * @param int $user_id

     * @param mixed $roleIds

     * 

     * @return boolean

     */ 

    function allocateRolesForUser($user_id,$roleIds){ 

        if (emptyempty($user_id)) return false; 

         

        $user_id = (int) $user_id; 

        $rsids = normalize($rsids,','); 

        if (emptyempty($rsids)){ 

            return false;        

        } 

         

        SingleTableCRUD::delete($this->tbRefUsersRoles,array('user_id'=>$user_id)); 

         

        $roleIds = array_unique($roleIds); 

         

        foreach ($roleIds as $roleId){ 

            SingleTableCRUD::insert($this->tbRefUsersRoles,array('user_id'=>$user_id,'role_id'=>$role_id)); 

        } 

        return true; 

    } 

         

    function cleanRolesForUser($user_id){ 

        if (emptyempty($user_id)) return false; 

        return SingleTableCRUD::delete($this->tbRefUsersRoles,array('user_id'=>(int) $user_id)); 

    } 

     

    function cleanUsersForRole($role_id){ 

        if (emptyempty($role_id)) return false; 

        return SingleTableCRUD::delete($this->tbRefUsersRoles,array('role_id'=>(int) $role_id)); 

    } 

     

 

/**

 * 對資源進行acl校驗

 * 

 * @param string $rsid 資源標識

 * @param array $user  特定用戶,不指定則校驗當前用戶

 * 

 * @return boolean

 */ 

function aclVerity($rsid,array $user = null){ 

    if (emptyempty($rsid)) return false; 

     

     

     

     

 

 

Java代碼 

/*

     * 校驗步驟如下:

     * 

     * 1. 先校驗 資源本身access 屬性

     *    EVERYONE => true,NOBODY  => false * 其它的屬性在下面繼續校驗

     * 2. 從session(或者 用戶session表)中獲取角色id集合

     * 3. 如果 用戶擁有角色 則HAS_ROLE => true , NO_ROLE => false;反之亦然

     * 4. 如果資源access == ALLOCATE_ROLES

     *      1. 從緩存(或者$tbRefResourcesRoles)中獲取 資源對應的角色id集合

     *      2. 將用戶擁有的角色id集合 與 資源對應的角色id集合求交集

     *      3. 存在交集=> true;否則=> false

     */  

 

花瞭半個小時 暈死 明天再抽空完善….

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。