浅析关于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实现批量查询清除一句话后门的代码
Jan 20 PHP
SWFUpload与CI不能正确上传识别文件MIME类型解决方法分享
Apr 18 PHP
php 数据库字段复用的基本原理与示例
Jul 22 PHP
xml在joomla表单中的应用详解分享
Jul 19 PHP
php读取纯真ip数据库使用示例
Jan 26 PHP
PHP常用数组函数介绍
Jul 28 PHP
php实现比较全的数据库操作类
Jun 18 PHP
WordPress后台中实现图片上传功能的实例讲解
Jan 11 PHP
php 访问oracle 存储过程实例详解
Jan 08 PHP
PHP基础之输出缓冲区基本概念、原理分析
Jun 19 PHP
thinkPHP5框架接口写法简单示例
Aug 05 PHP
PHP开启目录引索+fancyindex漂亮目录浏览带搜索功能
Sep 23 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技巧与注意事项分析
2011/02/03 PHP
discuz免激活同步登入代码修改方法(discuz同步登录)
2013/12/24 PHP
在PHP模板引擎smarty生成随机数的方法和math函数详解
2014/04/24 PHP
php文件操作相关类实例
2015/06/18 PHP
如何通过Linux命令行使用和运行PHP脚本
2015/07/29 PHP
php实现表单多按钮提交action的处理方法
2015/10/24 PHP
PHP面向对象之里氏替换原则简单示例
2018/04/08 PHP
一个收集图片的bookmarlet(js 刷新页面中的图片)
2010/05/27 Javascript
javascript 45种缓动效果 非常酷
2011/06/28 Javascript
Jquery命名冲突解决的五种方案分享
2012/03/16 Javascript
基于datagrid框架的查询
2013/04/08 Javascript
关于删除时的提示处理(确定删除吗)
2013/11/03 Javascript
node.js中的fs.writeFile方法使用说明
2014/12/14 Javascript
js超时调用setTimeout和间歇调用setInterval实例分析
2015/01/28 Javascript
jQuery绑定事件-多种实现方式总结
2016/05/09 Javascript
原生 JS Ajax,GET和POST 请求实例代码
2016/06/08 Javascript
indexedDB bootstrap angularjs之 MVC DOMO (应用示例)
2016/06/20 Javascript
JavaScript实现自定义媒体播放器方法介绍
2017/01/03 Javascript
nuxt.js 缓存实践
2018/06/25 Javascript
layui实现文件或图片上传记录
2018/08/28 Javascript
vue.js iview打包上线后字体图标不显示解决办法
2020/01/20 Javascript
vue从零实现一个消息通知组件的方法详解
2020/03/16 Javascript
ES6使用新特性Proxy实现的数据绑定功能实例
2020/05/11 Javascript
Element Notification通知的实现示例
2020/07/27 Javascript
vue 判断元素内容是否超过宽度的方式
2020/07/29 Javascript
五句话帮你轻松搞定js原型链
2020/12/09 Javascript
Python Web框架Flask下网站开发入门实例
2015/02/08 Python
实例Python处理XML文件的方法
2015/08/31 Python
python 阶乘累加和的实例
2019/02/01 Python
python GUI库图形界面开发之PyQt5 MDI(多文档窗口)QMidArea详细使用方法与实例
2020/03/05 Python
Brora官网:英国领先的羊绒服装品牌
2019/08/28 全球购物
预订旅游活动、景点和旅游:GetYourGuide
2019/09/29 全球购物
金蝶的一道SQL笔试题
2012/12/18 面试题
门卫工作岗位职责
2013/12/17 职场文书
日语专业求职信
2014/07/04 职场文书
简单介绍 http请求响应参数、无连接无状态、MIME、状态码、端口、telnet、curl
2021/03/31 HTML / CSS