浅析关于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 相关文章推荐
mysql 的 like 问题,超强毕杀记!!!
Jan 18 PHP
php防攻击代码升级版
Dec 29 PHP
PHP多例模式介绍
Jun 24 PHP
PHP生成Gif图片验证码
Oct 27 PHP
php中hashtable实现示例分享
Feb 13 PHP
php smarty模板引擎的6个小技巧
Apr 24 PHP
PHP中把stdClass Object转array的几个方法
May 08 PHP
PHP中使用file_get_contents抓取网页中文乱码问题解决方法
Dec 17 PHP
smarty内置函数foreach用法实例
Jan 22 PHP
php实现和c#一致的DES加密解密实例
Jul 24 PHP
详解PHP多个进程配合redis的有序集合实现大文件去重
Mar 06 PHP
Laravel访问出错提示:`Warning: require(/vendor/autoload.php): failed to open stream: No such file or di解决方法
Apr 02 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图片加水印实现方法
2016/05/06 PHP
php用户登录之cookie信息安全分析
2016/05/13 PHP
浅析PHP 中move_uploaded_file 上传中文文件名失败
2019/04/17 PHP
通过ifame指向的页面高度调整iframe的高度
2006/10/05 Javascript
JS 分号引起的一段调试问题
2009/06/18 Javascript
jQuery 技巧小结
2010/04/02 Javascript
jQuery结合PHP+MySQL实现二级联动下拉列表[实例]
2011/11/15 Javascript
javascript学习笔记(十六) 系统对话框(alert、confirm、prompt)
2012/06/20 Javascript
jquery阻止冒泡事件使用模拟事件
2013/09/06 Javascript
JS折半插入排序算法实例
2015/12/02 Javascript
jQuery动画效果图片轮播特效
2016/01/12 Javascript
星期几的不同脚本写法(推荐)
2016/06/01 Javascript
jquery实用技巧之输入框提示语句
2016/07/28 Javascript
微信小程序 教程之小程序配置
2016/10/17 Javascript
AngularJS $http模块POST请求实现
2017/04/08 Javascript
十分钟带你快速了解React16新特性
2017/11/10 Javascript
JS实现的判断方法、变量是否存在功能示例
2020/03/28 Javascript
JS实现全屏预览F11功能的示例代码
2018/07/23 Javascript
在vue项目中引入高德地图及其UI组件的方法
2018/09/04 Javascript
js实现搜索栏效果
2018/11/16 Javascript
Nodejs实现用户注册功能
2019/04/14 NodeJs
详解Vue template 如何支持多个根结点
2020/02/10 Javascript
[15:58]DOTA2国际邀请赛采访专栏:Tongfu.Sansheng&KingJ,DK.rOtk
2013/08/08 DOTA
Python格式化压缩后的JS文件的方法
2015/03/05 Python
python中的全局变量用法分析
2015/06/09 Python
TensorFlow实现AutoEncoder自编码器
2018/03/09 Python
500行代码使用python写个微信小游戏飞机大战游戏
2019/10/16 Python
Paradigit比利时电脑卖场:购买笔记本、电脑、平板和外围设备
2016/11/28 全球购物
德国最大的网上足球商店:11teamsports
2019/09/11 全球购物
《生命的药方》教学反思
2014/04/08 职场文书
老公保证书
2015/01/17 职场文书
2015年毕业实习工作总结
2015/05/29 职场文书
欢送会主持词
2015/07/01 职场文书
公司转让协议书
2016/03/19 职场文书
Python+Selenium自动化环境搭建与操作基础详解
2022/03/13 Python
linux目录管理方法介绍
2022/06/01 Servers