浅析关于PHP位运算的简单权限设计


Posted in PHP onJune 30, 2013

1.写在最前面
最近想写一个简单的关于权限处理的东西,之前我也了解过用二进制数的位运算可以出色地完成这个任务。关于二进制数的位运算,常见的就是“或、与、非”这三种简单运算了,当然,我也查看了下PHP手册,还有“异或、左移、右移”这三个运算。记得上初中时数学老师就开始唠叨个不停了,在此我也不想对此运算再作额外的说明,直接进入正题。

2.如何定义权限
将权限按照2的N次方来定义值,依次类推。为什么要这样子定义呐?这样子定义保证了每个权限值(二进制)中只有一个1,而它恰好对应一种权限。比如:

define('ADD', 1); // 增加权限
define('UPD', 2); // 修改权限
define('SEL', 4); // 查找权限
define('DEL', 8); // 删除权限

3.权限操作
权限操作其实涉及到“角色”这个概念。进行权限操作不外乎是让某个角色赋予某种权限、禁止某种权限和检测某个角色是否拥有某种权限。相对于这三个操作。可以用二进制数间的运算操作来很方便的实现。
// 给予某种权限用到“位或”运算符
$a_access = ADD | UPD | SEL | DEL; // a拥有增删改查权限
$b_access = ADD | UPD | SEL; // b拥有增改查权限
$c_access = ADD | UPD; // c拥有增改权限
// 禁止某种权限用“位与”和“位非”运算符
$d_access = $c_access & ~UPD; // d只拥有了增权限
// 检测是否拥有某种权限用到“位与”运算符
var_dump($b_access & ADD); // 1代表b拥有增权限
var_dump($b_access & DEL); // 0代表b不拥有删权限

4.实现简单的权限类和角色类
运用上面的权限操作方法,可以简单地封装成一个权限类和一个角色类。
/**
 * 简单权限类
 */
class Peak_Auth {
    /**
     * 权限类计数器
     * 作用在于生成权限值
     *
     * @var int
     */
    protected static $authCount = 0;
    /**
     * 权限名称
     *
     * @var string
     */
    protected $authName;
    /**
     * 权限详细信息
     *
     * @var string
     */
    protected $authMessage;
    /**
     * 权限值
     *
     * @var int 2的N次方
     */
    protected $authValue;
    /**
     * 构造函数
     * 初始化权限名称、权限详细信息以及权限值
     *
     * @param string $authName 权限名称
     * @param string $authMessage 权限详细信息
     */
    public function __construct($authName, $authMessage = '') {
        $this->authName = $authName;
        $this->authMessage = $authMessage;
        $this->authValue = 1 << self::$authCount;
        self::$authCount++;
    }
    /**
     * 本类不允许对象复制操作
     */
    private function __clone() {    }
    /**
     * 设置权限详细信息
     *
     * @param string $authMessage
     */
    public function setAuthMessage($authMessage) {
        $this->authMessage = $authMessage;
    }
    /**
     * 获取权限名称
     *
     * @return string
     */
    public function getAuthName() {
        return $this->authName;
    }
    /**
     * 获取权限值
     *
     * @return int
     */
    public function getAuthValue() {
        return $this->authValue;
    }
    /**
     * 获取权限详细信息
     *
     * @return string
     */
    public function getAuthMessage() {
        return $this->authMessage;
    }
}
/**
 * 简单角色类
 *
 * @author 27_Man
 */
class Peak_Role {
    /**
     * 角色名
     *
     * @var string
     */
    protected $roleName;
    /**
     * 角色拥有的权限值
     *
     * @var int
     */
    protected $authValue;
    /**
     * 父角色对象
     *
     * @var Peak_Role
     */
    protected $parentRole;
    /**
     * 构造函数
     *
     * @param string $roleName 角色名
     * @param Peak_Role $parentRole 父角色对象
     */
    public function __construct($roleName, Peak_Role $parentRole = null) {
        $this->roleName = $roleName;
        $this->authValue = 0;
        if ($parentRole) {
            $this->parentRole = $parentRole;
            $this->authValue = $parentRole->getAuthValue();
        }
    }
    /**
     * 获取父角色的权限
     */
    protected function fetchParenAuthValue() {
        if ($this->parentRole) {
            $this->authValue |= $this->parentRole->getAuthValue();
        }
    }
    /**
     * 给予某种权限
     *
     * @param Peak_Auth $auth
     * @return Peak_Role 以便链式操作
     */
    public function allow(Peak_Auth $auth) {
        $this->fetchParenAuthValue();
        $this->authValue |=  $auth->getAuthValue();
        return $this;
    }
    /**
     * 阻止某种权限
     *
     * @param Peak_Auth $auth
     * @return Peak_Role 以便链式操作
     */
    public function deny(Peak_Auth $auth) {
        $this->fetchParenAuthValue();
        $this->authValue &= ~$auth->getAuthValue();
        return $this;
    }
    /**
     * 检测是否拥有某种权限
     *
     * @param Peak_Auth $auth
     * @return boolean
     */
    public function checkAuth(Peak_Auth $auth) {
        return $this->authValue & $auth->getAuthValue();
    }
    /**
     * 获取角色的权限值
     *
     * @return int
     */
    public function getAuthValue() {
        return $this->authValue;
    }
}

5.对权限类和角色类的简单操作例子
// 创建三个权限:可读、可写、可执行
$read = new Peak_Auth('CanRead');
$write = new Peak_Auth('CanWrite');
$exe = new Peak_Auth('CanExe');
// 创建一个角色 User
$user = new Peak_Role('User');
// 创建另一个角色 Admin,他拥有 User 的所有权限
$admin = new Peak_Role('Admin', $user);
// 给予 User 可读、可写的权限
$user->allow($read)->allow($write);
// 给予 Admin 可执行的权限,另外他还拥有 User 的权限
$admin->allow($exe);
// 禁止 Admin 的可写权限
$admin->deny($write);
// 检测 Admin 是否具有 某种权限
var_dump($admin->checkAuth($read));
var_dump($admin->checkAuth($write));
var_dump($admin->checkAuth($exe));
PHP 相关文章推荐
一步一步学习PHP(5) 类和对象
Feb 16 PHP
php中通过curl smtp发送邮件
Jun 05 PHP
深入PHP中的HashTable结构详解
Jun 13 PHP
php curl获取网页内容(IPV6下超时)的解决办法
Jul 16 PHP
windwos下使用php连接oracle数据库的过程分享
May 26 PHP
PHPAnalysis中文分词类详解
Jun 13 PHP
PHP获取数组最后一个值的2种方法
Jan 21 PHP
php随机生成数字字母组合的方法
Mar 18 PHP
PHP生成和获取XML格式数据的方法
Mar 04 PHP
PHP 生成微信红包代码简单
Mar 25 PHP
PHP树-不需要递归的实现方法
Jun 21 PHP
ThinkPHP5.1+Ajax实现的无刷新分页功能示例
Feb 10 PHP
PHP删除HTMl标签的三种解决方法
Jun 30 #PHP
PHP删除HTMl标签的实现代码
Jun 30 #PHP
浅析php面向对象public private protected 访问修饰符
Jun 30 #PHP
解析link_mysql的php版
Jun 30 #PHP
分享8个最佳的代码片段在线测试网站
Jun 29 #PHP
php 验证码(倾斜,正弦干扰线,黏贴,旋转)
Jun 29 #PHP
浅谈web上存漏洞及原理分析、防范方法(文件名检测漏洞)
Jun 29 #PHP
You might like
php图片的二进制转换实现方法
2014/12/15 PHP
PHP的图像处理实例小结【文字水印、图片水印、压缩图像等】
2019/12/20 PHP
延时重复执行函数 lLoopRun.js
2007/05/08 Javascript
jquery获取input表单值的代码
2010/04/19 Javascript
JavaScript中清空数组的三种方法分享
2011/04/07 Javascript
jQuery筛选器children()案例详解(图文)
2013/02/17 Javascript
JavaScript function 的 length 属性使用介绍
2014/09/15 Javascript
js实现进度条的方法
2015/02/13 Javascript
深入学习jQuery Validate表单验证(二)
2016/01/18 Javascript
关于原生js中bind函数的简单实现
2016/08/10 Javascript
jQuery Validate表单验证插件的基本使用方法及功能拓展
2017/01/04 Javascript
微信小程序商城项目之商品属性分类(4)
2017/04/17 Javascript
基于axios封装fetch方法及调用实例
2018/02/05 Javascript
vue.js 底部导航栏 一级路由显示 子路由不显示的解决方法
2018/03/09 Javascript
bootstrap模态框弹出和隐藏,动态改变中间内容的实例
2018/08/10 Javascript
layui 监听select选择 获取当前select的ID名称方法
2019/09/24 Javascript
Layui实现数据表格默认全部显示(不要分页)
2019/10/26 Javascript
详解基于element的区间选择组件校验(交易金额)
2021/01/07 Javascript
python利用装饰器进行运算的实例分析
2015/08/04 Python
Python实现遍历目录的方法【测试可用】
2017/03/22 Python
Python日志syslog使用原理详解
2020/02/18 Python
在Python中使用K-Means聚类和PCA主成分分析进行图像压缩
2020/04/10 Python
python退出循环的方法
2020/06/18 Python
HTML5中图片之间的缝隙完美解决方法
2017/07/07 HTML / CSS
拉斯维加斯酒店、演出、旅游、俱乐部及更多:Vegas.com
2019/02/28 全球购物
俄罗斯园林植物网上商店:Garshinka
2020/07/16 全球购物
一月红领巾广播稿
2014/02/11 职场文书
维修工先进事迹
2014/05/29 职场文书
大学生交通专业求职信
2014/09/01 职场文书
2014会计年终工作总结
2014/12/20 职场文书
退税申请报告怎么写
2015/05/18 职场文书
岁月神偷观后感
2015/06/11 职场文书
导游词之无锡华莱坞
2019/12/02 职场文书
MySQL 分区表中分区键为什么必须是主键的一部分
2022/03/17 MySQL
Meta增速拉垮,元宇宙难当重任
2022/04/29 数码科技
ant design charts 获取后端接口数据展示
2022/05/25 Javascript